狀壓dp--bzoj4145: [AMPPZ2014]The Prices
阿新 • • 發佈:2018-12-16
傳送門 狀壓,列舉子集過不了 考慮轉移的時候,一開始先假設在這個商店買了,令 然後列舉不在集合的物品進行轉移,最後讓 複雜度在上是能過的
這種就是先假設做了某件事最後再看到底做不做哪個更優來降低複雜度的
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 105
#define maxm 16
using namespace std;
int n,m,d[maxn],c[maxn][maxm],f[maxn][(1<<maxm)+5];
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9' ) f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
int main(){
n=rd(); m=rd();
for(register int i=1;i<=n;i++) {
d[i]=rd();
for(register int j=1;j<=m;j++) c[i][j]=rd();
}
memset(f,0x3f,sizeof f);
f[0][0]=0;
for(register int i=1;i<= n;i++){
for(register int j=0;j<(1<<m);j++)
f[i][j]=f[i-1][j]+d[i];
for(register int j=0;j<(1<<m);j++)
for(register int k=1;k<=m;k++)
if(!(j&(1<<(k-1)))){
f[i][j|(1<<(k-1))]=min(f[i][j|(1<<(k-1))],f[i][j]+c[i][k]);
}
for(register int j=0;j<(1<<m);j++) f[i][j]=min(f[i-1][j],f[i][j]);
}
printf("%d\n",f[n][(1<<m)-1]);
return 0;
}