BZOJ4145_The Prices_KEY
看到M<=16经典状态压缩的数据范围,考虑题目。
一道类似于背包的题目。
设f[i][j]表示前i个商店,物品购买状态为j。
先将f[i][j]加上w[i](到i的路费),转移一次,在与同状态的前一商店取min就好了。
code:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int N,M,a[105][20],w[105]; int f[105][1<<16]; int main() { scanf("%d%d",&N,&M); for(int i=1;i<=N;i++){ scanf("%d",&w[i]); for(int j=1;j<=M;j++)scanf("%d",&a[i][j]); } for(int S=1;S<1<<M;S++)f[0][S]=1e9; for(int i=1;i<=N;i++){ for(int S=0;S<1<<M;S++)f[i][S]=f[i-1][S]+w[i]; for(int S=0;S<1<<M;S++) for(int j=1;j<=M;j++) if(!(S&(1<<j-1)))f[i][S|(1<<j-1)]=min(f[i][S|(1<<j-1)],f[i][S]+a[i][j]); for(int S=0;S<1<<M;S++)f[i][S]=min(f[i][S],f[i-1][S]); } printf("%d",f[N][(1<<M)-1]); return 0; }