POJ2288 Islands and Bridges(TSP:状压DP)

求一个图的哈密顿路径的最大权及其路径数。显然状态压缩+DP。

dp[v][u][S] 表示从v走到当前顶点 u且走过的顶点集合是S的 最大权值和方案数

这题我用记忆化搜索,从终点开始递归进行,感觉这样比较容易转移。

就是搜索一个状态可以从哪些状态转移过来,顺便统计方案数。搜索时要注意一些细节,转移要合法还有可能某个状态是无解的要跳过

还有一些细节什么什么的。。 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 bool G[13][13];
 6 int n,val[13];
 7 __int64 d[13][13][1<<13],cnt[13][13][1<<13];
 8 __int64 dfs(int u1,int u2,int S){
 9     if(d[u1][u2][S]!=-1) return d[u1][u2][S];
10     int res=0;
11     for(int u0=0; u0<n; ++u0){
12         if(u0==u1 || u0==u2 || !G[u0][u1] || ((S>>u0)&1)==0) continue;
13         if(dfs(u0,u1,S^(1<<u2))==0) continue;
14         int tmp=dfs(u0,u1,S^(1<<u2))+val[u1]*val[u2];
15         if(G[u0][u2]) tmp+=val[u0]*val[u1]*val[u2];
16         res=max(res,tmp);
17     }
18     for(int u0=0; u0<n; ++u0){
19         if(u0==u1 || u0==u2 || !G[u0][u1] || ((S>>u0)&1)==0) continue;
20         if(dfs(u0,u1,S^(1<<u2))==0) continue;
21         int tmp=dfs(u0,u1,S^(1<<u2))+val[u1]*val[u2];
22         if(G[u0][u2]) tmp+=val[u0]*val[u1]*val[u2];
23         if(res==tmp) cnt[u1][u2][S]+=cnt[u0][u1][S^(1<<u2)];
24     }
25     return d[u1][u2][S]=res;
26 }
27 int main(){
28     int t,m,a,b;
29     scanf("%d",&t);
30     while(t--){
31         memset(d,-1,sizeof(d));
32         memset(cnt,0,sizeof(cnt));
33         memset(G,0,sizeof(G));
34         scanf("%d%d",&n,&m);
35         int sum=0;
36         for(int i=0;i<n;++i) scanf("%d",val+i),sum+=val[i];
37         while(m--){
38             scanf("%d%d",&a,&b);
39             --a; --b;
40             G[a][b]=G[b][a]=1;
41         }
42         if(n==1){
43             printf("%d %d\n",val[0],1);
44             continue;
45         }
46         for(int i=0; i<n; ++i){
47             for(int j=0; j<n; ++j){
48                 if(i==j || !G[i][j]) continue;
49                 d[i][j][(1<<i)|(1<<j)]=val[i]*val[j];
50                 cnt[i][j][(1<<i)|(1<<j)]=1;
51             }
52         }
53         __int64 res=0,num=0;
54         for(int i=0; i<n; ++i){
55             for(int j=0; j<n; ++j){
56                 if(i==j || !G[i][j]) continue;
57                 res=max(res,dfs(i,j,(1<<n)-1));
58             }
59         }
60         for(int i=0; i<n; ++i){
61             for(int j=0; j<n; ++j){
62                 if(i==j || !G[i][j]) continue;
63                 if(res==dfs(i,j,(1<<n)-1)) num+=cnt[i][j][(1<<n)-1];
64             }
65         }
66         if(res) res+=sum;
67         printf("%I64d %I64d\n",res,num>>1);
68     }
69     return 0;
70 }

 

posted @ 2016-01-10 17:10  WABoss  阅读(188)  评论(0编辑  收藏  举报