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 }
View Code

 

posted @ 2018-03-30 12:47  鲸头鹳  阅读(148)  评论(0编辑  收藏  举报