zoukankan      html  css  js  c++  java
  • PKU 2288 Islands and Bridges 状态dp

    题意:

      给你一张地图,上面有一些岛和桥。你要求出最大的三角哈密顿路径,以及他们的数量。

      哈密顿路:一条经过所有岛的路径,每个岛只经过一次。

      最大三角哈密顿路:满足价值最大的哈密顿路。

        价值计算分为以下三部分:

          1. 所有点权的和。

          2. 对于路径上任意两个连续的点(共享一条边)的点权乘积的和。

          3. 对于路径上任意三个连续的点,如果他们构成一个三角形(两两之间有边),那么加上三点点权的乘积

    思路:

      状态压缩动态规划, dp[st][i][j] 表示状态是st, 前一步在i,现在停在j的最大价值。

        cnt[st][i][j] 表示计数。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 typedef __int64 ll;
     8 
     9 const int MAXN= 13;
    10 
    11 ll dp[1<<13][MAXN][MAXN];
    12 ll cnt[1<<13][MAXN][MAXN];
    13 
    14 int G[20][20];
    15 ll val[20];
    16 int n, m;
    17 
    18 void print() {
    19     for (int i = 0; i <= n; i++) {
    20         for (int j = 0; j <= n; j++)
    21             printf("%d ", G[i][j]);
    22         puts("");
    23     }
    24 }
    25 
    26 int main() {
    27     #ifdef Phantom01
    28         freopen("PKU2288.txt", "r", stdin);
    29     #endif // Phantom01
    30 
    31     int T;
    32     scanf("%d", &T);
    33     while (T--) {
    34         scanf("%d%d", &n, &m);
    35         memset(dp, 0, sizeof(dp));
    36         memset(cnt, 0, sizeof(cnt));
    37         memset(G, 0, sizeof(G));
    38         for (int i = 0; i < n; i++) {
    39             scanf("%I64d", &val[i]);
    40         }
    41         for (int i = 0; i < m; i++) {
    42             int u, v;
    43             scanf("%d%d", &u, &v);
    44             G[u-1][v-1] += 1;
    45             G[v-1][u-1] += 1;
    46         }
    47 //print();
    48         if (1==n) {
    49             printf("%I64d 1
    ", val[0]);
    50             continue;
    51         }
    52 
    53         for (int i = 0; i < n; i++)
    54             for (int j = 0; j < n; j++) if (G[i][j]){
    55                 dp[(1<<i)|(1<<j)][i][j] = val[i] + val[j] + val[i]*val[j];
    56                 cnt[(1<<i)|(1<<j)][i][j] += G[i][j];
    57             }
    58 
    59         for (int i = 1; i < (1<<n)-1; i++)
    60             for (int j = 0; j < n; j++) if (i&(1<<j))
    61                 for (int u = 0; u < n; u++) if ((i&(1<<u)) && (j!=u) && cnt[i][j][u])
    62                     for (int v = 0; v < n; v++) if (G[u][v] && !(i&(1<<v))) {
    63                         ll &now = dp[i][j][u];
    64                         ll &next = dp[i|(1<<v)][u][v];
    65                         ll va = val[v]*(1 + val[u]);
    66                         if (G[j][v]) va += val[j]*val[u]*val[v];
    67                         if (next < now+va) {
    68                             next = now+va;
    69                             cnt[i|(1<<v)][u][v] = cnt[i][j][u];
    70                         } else if (next==now+va)
    71                             cnt[i|(1<<v)][u][v] += cnt[i][j][u];
    72                     }
    73 
    74         ll ans = 0, c = 0;
    75         for (int i = 0; i < n; i++)
    76             for (int j = 0; j < n; j++)
    77                 if (ans<dp[(1<<n)-1][i][j]) {
    78                     ans = dp[(1<<n)-1][i][j];
    79                     c = cnt[(1<<n)-1][i][j];
    80                 } else if (ans==dp[(1<<n)-1][i][j])
    81                     c += cnt[(1<<n)-1][i][j];
    82 
    83         printf("%I64d %I64d
    ", ans, c/2);
    84     }
    85 
    86     return 0;
    87 }
    PKU2288

    P.s.: 开始多开了一维导致MLE,后来发现读错题了 0 0 结果花了一晚上

  • 相关阅读:
    此类目的是防治序列化Json字符串时的循环引用问题-------最好解决方案
    Json.Net学习笔记
    深入理解javascript原型和闭包(完结)
    SDL 威胁建模工具入门 threat modeling tool
    .NET 4.0 中的契约式编程
    MVC调用部分视图PartialView
    visual studio 常识
    【阿里云产品评测】小鸡咕咕的初体验
    【阿里云入门产品免费试用半年】加入微博话题+“最”炫推荐理由,得精美小礼物
    镜像公测招募啦!!!用镜像开通云服务器,限时免费体验!!
  • 原文地址:https://www.cnblogs.com/Phantom01/p/3687187.html
Copyright © 2011-2022 走看看