zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",res,num>>1);
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    截取文件路径组成新文件路径
    jsoup选择器
    正则小示例
    一个没有经过优化的过滤指定目录下的指定扩展名文件的算法
    正则表达式生成问题
    链接中带换行的页面查找替换问题
    数组扩容测试
    LeetCode 3.无重复字符的最长子串
    LeetCode 200.岛屿数量
    LeetCode 560.和为K的子数组
  • 原文地址:https://www.cnblogs.com/WABoss/p/5118763.html
Copyright © 2011-2022 走看看