zoukankan      html  css  js  c++  java
  • poj 2288 Islands and Bridges

    题意:

    定义一个最优哈密顿回路如果把如下描述的值最大化:

    有n个城市。一个哈密顿回路C1C2..Cn的值由3个部分组成:

    1.这个路径上每个岛的值Vi之和;

    2.这个路径上每条边Vi*Vi+1之和;

    3.如果路径上连续的三个岛屿CiCi+1Ci+2之间两两互相连通,那么就加上Vi*Vi+1*Vi+2。

    求出最优哈密顿回路的值以及个数。

    (一条路径及其反转,认为是同一条路径)。

    思路:

    首先,计算值肯定是跟前两个岛有关系的,此时就可以用当前状态为S,前两个岛为i,前一个岛为j来进行状态的转移。

    dp[S|(1<<k)][j][k] = max(dp[S|(1<<k)][j][k],dp[S][i][j] + v[k] + v[j]*v[k] + v[j]*v[k]*v[i]),最后一个部分必须满足两两互相连通才能加。

    如果dp[S|(1<<k)][j][k]已经有值并且与当前计算出来的值相同,路径条数直接加上即可。

    最后路径条数要减半,因为逆序的路径也是计算了的。

    注意dp数组的初始化。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 using namespace std;
      5 const int N = 14;
      6 int dp[1<<N][N][N];
      7 long long num[1<<N][N][N];
      8 int v[N];
      9 bool mp[N][N];
     10 int main()
     11 {
     12     int t;
     13     scanf("%d",&t);
     14     while (t--)
     15     {
     16         int n,m;
     17         scanf("%d%d",&n,&m);
     18         memset(mp,0,sizeof(mp));
     19         memset(dp,-1,sizeof(dp));
     20         memset(num,0,sizeof(num));
     21         for (int i = 0;i < n;i++) scanf("%d",&v[i]);
     22         for (int i = 0;i < m;i++)
     23         {
     24             int x,y;
     25             scanf("%d%d",&x,&y);
     26             x--,y--;
     27             mp[x][y] = mp[y][x] = 1;
     28         }
     29         if (n == 1)
     30         {
     31             printf("%d 1
    ",v[0]);
     32             continue;
     33         }
     34         for (int i = 0;i < n;i++)
     35         {
     36             for (int j = 0;j < n;j++)
     37             {
     38                 if (i == j) continue;
     39                 if (!mp[i][j]) continue;
     40                 dp[(1<<i)|(1<<j)][i][j] = v[i] + v[j] + v[i]*v[j];
     41                 num[(1<<i)|(1<<j)][i][j] = 1;
     42             }
     43         }
     44         for (int i = 0;i < (1<<n);i++)
     45         {
     46             for (int j = 0;j < n;j++)
     47             {
     48                 for (int k = 0;k < n;k++)
     49                 {
     50                     if (j == k) continue;
     51                     if (!mp[j][k]) continue;
     52                     if (dp[i][j][k] < 0) continue;
     53                     for (int l = 0;l < n;l++)
     54                     {
     55                         if (i&(1<<l)) continue;
     56                         if (!mp[k][l]) continue;
     57                         int tmp = v[l] + v[k] * v[l];
     58                         if (mp[j][k] && mp[j][l] && mp[l][k])
     59                         {
     60                             tmp += v[j]*v[k]*v[l];
     61                         }
     62                         if (dp[i|(1<<l)][k][l] < dp[i][j][k] + tmp)
     63                         {
     64                             dp[i|(1<<l)][k][l] = dp[i][j][k] + tmp;
     65                             num[i|(1<<l)][k][l] = num[i][j][k];
     66                         }
     67                         else if (dp[i|(1<<l)][k][l] == dp[i][j][k] + tmp)
     68                         {
     69                             num[i|(1<<l)][k][l] += num[i][j][k];
     70                         }
     71                     }
     72                 }
     73             }
     74         }
     75         int maxn = -1;
     76         long long cnt = 0;
     77         for (int i = 0;i < n;i++)
     78         {
     79             for (int j = 0;j < n;j++)
     80             {
     81                 if (i == j) continue;
     82                 maxn = max(dp[(1<<n)-1][i][j],maxn);
     83             }
     84         }
     85         if (maxn == -1) printf("0 0
    ");
     86         else
     87         {
     88             for (int i = 0;i < n;i++)
     89             {
     90                 for (int j = 0;j < n;j++)
     91                 {
     92                     if (i == j) continue;
     93                     if (dp[(1<<n)-1][i][j] == maxn) cnt += num[(1<<n)-1][i][j];
     94                 }
     95             }
     96             printf("%d %lld
    ",maxn,cnt/2);
     97         }
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    得到cxgrid筛选后的记录数
    服务器之ipmitool
    CentOS6.8部署SVN
    NGINX快速部署
    Nginx模块系列之auth_basic模块
    持续集成、持续交付、持续部署
    CentOS6.X 升级内核至 3.10
    Dmidecode
    新建虚拟机
    Linux之(tomcat)服务之服务调优
  • 原文地址:https://www.cnblogs.com/kickit/p/8860487.html
Copyright © 2011-2022 走看看