• Islands and Bridges(POJ2288+状压dp+Hamilton 回路)


    题目链接:http://poj.org/problem?id=2288

    题目:

    题意:求Hamilton 路径权值的最大值,且求出有多少条权值这么大的Hamilton路径。

    思路:状压dp,dp[i][j][k]表示第i种状态下倒数第二个岛屿为j倒数第一个岛屿为k下的权值,cnt[i][j][k]记录条数。

      当有边(i,j)存在时,有如下初值可赋:
      d[(1<<i)+(1<<j)][i][j]=val[i]+val[j]+val[i]*val[j],cnt[(1<<i)+(1<<j)][i][j]=1。
       如果状态(state,i,j)可达,检查岛k,如果此时k没有被访问过并且有边(j,k)存在,则做如下操作:
      1)设tmp为下一步访问岛k时获得的总利益,r=state+(1<<k)。
      2)如果tmp>d[r][j][k],表示此时可以更新到更优解,则更新:
          d[r][j][k]=tmp,cnt[r][j][k]=cnt[state][i][j]。
      3)如果tmp==d[r][j][k],表示此时可以获得达到局部最优解的更多方式,则更新:
          cnt[r][j][k]+=cnt[state][i][j]。
      最后检查所有的状态((1<<n)-1,i,j),叠加可以得到最优解的道路数。
      需要注意的是,题目约定一条路径的两种行走方式算作一种,所以最终结果要除2。

    代码实现如下:

      1 #include <set>
      2 #include <map>
      3 #include <queue>
      4 #include <stack>
      5 #include <cmath>
      6 #include <bitset>
      7 #include <cstdio>
      8 #include <string>
      9 #include <vector>
     10 #include <cstdlib>
     11 #include <cstring>
     12 #include <iostream>
     13 #include <algorithm>
     14 using namespace std;
     15 
     16 typedef long long ll;
     17 typedef pair<ll, ll> pll;
     18 typedef pair<ll, int> pli;
     19 typedef pair<int, ll> pil;;
     20 typedef pair<int, int> pii;
     21 typedef unsigned long long ull;
     22 
     23 #define lson i<<1
     24 #define rson i<<1|1
     25 #define bug printf("*********
    ");
     26 #define FIN freopen("D://code//in.txt", "r", stdin);
     27 #define debug(x) cout<<"["<<x<<"]" <<endl;
     28 #define IO ios::sync_with_stdio(false),cin.tie(0);
     29 
     30 const double eps = 1e-8;
     31 const int mod = 10007;
     32 const int maxn = (1<<13) + 7;
     33 const double pi = acos(-1);
     34 const int inf = 0x3f3f3f3f;
     35 const ll INF = 0x3f3f3f3f3f3f3f;
     36 
     37 int t, n, m, u, v;
     38 int w[13], mp[15][15];
     39 ll dp[maxn][13][13], cnt[maxn][15][15];
     40 
     41 int main() {
     42     //FIN;
     43     scanf("%d", &t);
     44     while(t--) {
     45         memset(mp, 0, sizeof(mp));
     46         memset(dp, -1, sizeof(dp));
     47         memset(cnt, 0, sizeof(cnt));
     48         scanf("%d%d", &n, &m);
     49         for(int i = 1; i <= n; ++i) {
     50             scanf("%d", &w[i]);
     51         }
     52         for(int i = 1; i <= m; ++i) {
     53             scanf("%d%d", &u, &v);
     54             mp[u][v] = mp[v][u] = 1;
     55         }
     56         if(n == 1) {
     57             printf("%d 1
    ", w[1]);
     58             continue;
     59         }
     60         for(int i = 1; i <= n; ++i) {
     61             for(int j = 1; j <= n; ++j) {
     62                 if(i != j && mp[i][j]) {
     63                     dp[(1<<(i-1))|(1<<(j-1))][i][j] = w[i] + w[j] + (ll) w[i] * w[j];
     64                     cnt[(1<<(i-1))|(1<<(j-1))][i][j] = 1;
     65                 }
     66             }
     67         }
     68         int tot = 1 << n;
     69         for(int i = 0; i < tot; ++i) {
     70             for(int j = 1; j <= n; ++j) {
     71                 if(i & (1<<(j-1))) {
     72                     for(int k = 1; k <= n; ++k) {
     73                         if(j != k && (i & (1<<(k-1))) && mp[j][k] && dp[i][j][k] != -1) {
     74                             for(int x = 1; x <= n; ++x) {
     75                                 if(j != x && k != x && mp[k][x] && (i & (1<<(x-1))) == 0) {
     76                                     ll tmp = dp[i][j][k] + w[x] + (ll)w[k] * w[x];
     77                                     if(mp[j][x]) tmp += (ll)w[k] * w[j] * w[x];
     78                                     if(tmp > dp[i|(1<<(x-1))][k][x]) {
     79                                         dp[i|(1<<(x-1))][k][x] = tmp;
     80                                         cnt[i|(1<<(x-1))][k][x] = cnt[i][j][k];
     81                                     } else if(tmp == dp[i|(1<<(x-1))][k][x]){
     82                                         cnt[i|(1<<(x-1))][k][x] += cnt[i][j][k];
     83                                     }
     84                                 }
     85                             }
     86                         }
     87                     }
     88                 }
     89             }
     90         }
     91         ll ans1 = 0, ans2 = 0;
     92         for(int i = 1; i <= n; ++i) {
     93             for(int j = 1; j <= n; ++j) {
     94                 if(i == j) continue;
     95                 if(dp[tot-1][i][j] > ans1) {
     96                     ans1 = dp[tot-1][i][j];
     97                     ans2 = cnt[tot-1][i][j];
     98                 } else if(dp[tot-1][i][j] == ans1) {
     99                     ans2 += cnt[tot-1][i][j];
    100                 }
    101             }
    102         }
    103         printf("%lld %lld
    ", ans1, ans2 / 2);
    104     }
    105     return 0;
    106 }
  • 相关阅读:
    PHP mysqli 扩展库(面向对象/数据库操作封装/事务控制/预编译)
    php 下载文件的函数
    PBOC电子钱包与电子现金及QPBOC
    基于PBOC电子钱包的消费过程详解
    PBOC规范下的java卡介绍
    基于PBOC电子钱包的圈存过程详解
    电子钱包和电子现金的区别
    DES,3DES,AES这三种对称密钥的区别与联系
    密钥体系
    关于卡片的主控密钥和应用主控密钥
  • 原文地址:https://www.cnblogs.com/Dillonh/p/9450171.html
Copyright © 2020-2023  润新知