LOJ P3959 宝藏 状压dp noip
https://www.luogu.org/problemnew/show/P3959
考场上我怎么想不出来这么写的,状压白学了。
直接按层次存因为如果某个点在前面存过了则肯定结果更优所以不用在意各点的层次只用在意最深的点的层次。
调的时候因为e最开始初始化太大了溢出了好几次mdzz。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<vector> 7 using namespace std; 8 const int maxn=600010; 9 int n,m; 10 int e[15][15]={}; 11 int f[15][4400]={}; 12 int yu[4400]={},v[15]={},id[15]={},tot; 13 int p[4400]={},qun[4400]={}; 14 int main(){ 15 memset(e,1,sizeof(e)); 16 memset(f,63,sizeof(f)); 17 //cout<<e[0][0]<<endl; 18 scanf("%d%d",&n,&m); 19 int x,y,val,mx=(1<<n),mnum=f[0][0]; 20 for(int i=1;i<=m;i++){ 21 scanf("%d%d%d",&x,&y,&val); 22 e[x][y]=min(val,e[x][y]);e[y][x]=e[x][y]; 23 } 24 for(int i=1;i<=n;i++)yu[1<<(i-1)]=i; 25 for(int i=1;i<=n;i++)f[1][1<<(i-1)]=0; 26 for(int i=1;i<n;i++){ 27 for(int j=1;j<mx;j++){ 28 tot=0; 29 for(int w=1;w<=n;w++){ 30 if((1<<(w-1))&j)continue; 31 v[++tot]=mnum;id[tot]=1<<(w-1); 32 for(int z=j;z;z-=(z&-z)) 33 v[tot]=min(v[tot],e[yu[z&-z]][w]*i); 34 } 35 int mn=(1<<tot); 36 for(int w=1;w<mn;w++){ 37 p[w]=p[w-(w&-w)]+v[yu[w&-w]]; 38 qun[w]=qun[w-(w&-w)]|id[yu[w&-w]]; 39 f[i+1][j|qun[w]]=min(f[i+1][j|qun[w]],f[i][j]+p[w]); 40 } 41 } 42 } 43 int ans=mnum; 44 for(int i=1;i<=n+1;i++)ans=min(ans,f[i][mx-1]); 45 printf("%d\n",ans); 46 return 0; 47 }