Problem
【AMPPZ2014】The Prices
TimeLimit:20Sec
MemoryLimit:256MB
Description
你要购买m种物品各一件,一共有n家商店,你到第i家商店的路费为d[i],在第i家商店购买第j种物品的费用为c[i][j],求最小总费用。
第一行包含两个正整数n,m(1≤n≤100,1≤m≤16),表示商店数和物品数。
接下来n行,每行第一个正整数d[i](1≤d[i]≤106)表示到第i家商店的路费,接下来m个正整数,
依次表示c[i][j](1≤c[i][j]<106)。
Output
一个正整数,即最小总费用。
1 2 3 4
| 3 4 5 7 3 7 9 2 1 20 3 2 8 1 20 1 1
|
Sample Output
HINT
在第一家店买2号物品,在第二家店买剩下的物品。
标签:状压DP
Solution
M≤16,显然是一道状压DP。
用f[i][j]表示考虑1∼i家商店,购买状态为j的方案数。套路状压转移即可。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <bits/stdc++.h> #define MAX_N 100 #define MAX_M 16 using namespace std; typedef long long lnt; int n, m, d[MAX_N+5], c[MAX_N+5][MAX_M+5], f[MAX_N+5][(1<<MAX_M)+5]; int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) {scanf("%d", d+i); for (int j = 1; j <= m; j++) scanf("%d", c[i]+j);} memset(f, 0x3f, sizeof f); f[0][0] = 0; for (int i = 1; i <= n; i++) { for (int j = 0; j < (1<<m); j++) f[i][j] = f[i-1][j]+d[i]; for (int k = 1; k <= m; k++) for (int j = 0; j < (1<<m); j++) if ((j&(1<<k-1)) == 0) f[i][j|(1<<k-1)] = min(f[i][j]+c[i][k], f[i][j|(1<<k-1)]); for (int j = 0; j < (1<<m); j++) f[i][j] = min(f[i][j], f[i-1][j]); } printf("%d", f[n][(1<<m)-1]); return 0; }
|