zoukankan      html  css  js  c++  java
  • POJ 2288 Islands and Bridges(状压dp)

    http://poj.org/problem?id=2288

    题意:

    有n个岛屿,每个岛屿有一个权值V,一条哈密顿路径C1,C2,...Cn的值为3部分之和:

    第1部分,将路径中每个岛屿的权值累加起来;第2部分,对路径中的每条边(Ci,Ci+1),将成绩Vi×Vi+1累加起来;第3部分,当路径中连续的3个岛屿Ci、Ci+1和Ci+2形成一个三角形,即在岛屿Ci和Ci+2之间有一座桥,则把乘积Vi×Vi+1×Vi+2累加起来。

    寻找权值最大的哈密顿路径和其路径数。

    思路:

    用d【status】【i】【j】表示当前状态为status,并且最后两个顶点分别为 i 和 j 时的最大权值,同理,ways【status】【i】【j】表示此时对应的路径的数量。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<sstream>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 #include<cmath>
     10 #include<map>
     11 #include<set>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,int> pll;
     15 const int INF = 0x3f3f3f3f;
     16 const int maxn = 1000 + 5;
     17 
     18 int n, m;
     19 
     20 int val[13];
     21 int g[13][13];
     22 ll d[1<<13][13][13];
     23 ll ways[1<<13][13][13];
     24 
     25 int main()
     26 {
     27     //freopen("in.txt","r",stdin);
     28     int T;
     29     scanf("%d",&T);
     30     while(T--)
     31     {
     32         memset(g,0,sizeof(g));
     33         memset(d,-1,sizeof(d));
     34         memset(ways,0,sizeof(ways));
     35 
     36         scanf("%d%d",&n,&m);
     37         for(int i=0;i<n;i++)  scanf("%d",&val[i]);
     38         for(int i=0;i<m;i++)
     39         {
     40             int u, v;
     41             scanf("%d%d",&u, &v);
     42             u--; v--;
     43             g[u][v]=g[v][u]=1;
     44             //初始化
     45             d[(1<<u)|(1<<v)][u][v]=d[(1<<u)|(1<<v)][v][u]=val[u]+val[v]+val[u]*val[v];
     46             ways[(1<<u)|(1<<v)][u][v]=ways[(1<<u)|(1<<v)][v][u]=1;
     47         }
     48 
     49         ll maxvalue=-1;
     50         ll maxways=0;
     51 
     52         if(n==1)  {maxvalue=val[0];maxways=1;} //如果只有一个顶点,则特判
     53 
     54         if(n!=1)
     55         for(int s=0;s<(1<<n);s++)
     56         {
     57             for(int i=0;i<n;i++)
     58             {
     59                 if(s&(1<<i))
     60                 for(int j=0;j<n;j++)
     61                 {
     62                     if((i!=j) && (s&(1<<j)) &&d[s][i][j]>-1)
     63                     {
     64                         for(int k=0;k<n;k++) //枚举新加入的顶点
     65                         {
     66                             if(!(s&(1<<k)) && g[j][k])
     67                             {
     68                                 int nextstatus=s|(1<<k);
     69                                 ll tmp = d[s][i][j]+val[k]+val[j]*val[k];
     70                                 if(g[i][k])  //如果Ci和Ci+2之间存在桥
     71                                     tmp+=val[i]*val[j]*val[k];
     72 
     73                                 if(d[nextstatus][j][k]==tmp)
     74                                 {
     75                                     ways[nextstatus][j][k]+=ways[s][i][j];
     76                                 }
     77                                 else if(d[nextstatus][j][k]<tmp)
     78                                 {
     79                                     d[nextstatus][j][k]=tmp;
     80                                     ways[nextstatus][j][k]=ways[s][i][j];
     81                                 }
     82                             }
     83                         }
     84                     }
     85                 }
     86             }
     87         }
     88 
     89         int s=(1<<n)-1;
     90         if(n!=1)
     91         for(int i=0;i<n;i++)
     92         {
     93             for(int j=0;j<n;j++)
     94             {
     95                 if(g[i][j]==0)  continue;
     96                 if(d[s][i][j]>maxvalue)
     97                 {
     98                     maxvalue=d[s][i][j];
     99                     maxways=ways[s][i][j];
    100                 }
    101                 else if(d[s][i][j]==maxvalue)
    102                     maxways+=ways[s][i][j];
    103             }
    104         }
    105         if(n!=1)  maxways/=2;  //因为正向和逆向是一样的,所以这里除2
    106         if(maxvalue==-1)  puts("0 0");
    107         else printf("%lld %lld
    ",maxvalue,maxways);
    108     }
    109     return 0;
    110 }
  • 相关阅读:
    从零开始学Kotlin-使用接口(7)
    从零开始学Kotlin-类的继承(6)
    从零开始学Kotlin-类和对象(5)
    从零开始学Kotlin-控制语句(4)
    从零开始学Kotlin-操作符(3)
    从零开始学Kotlin-数据类型(2)
    从零开始学Kotlin-基础语法(1)
    Java设计模式之单例模式(七种写法)
    一个简单的可控的头像列表叠加控件
    使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种滑动冲突
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7198529.html
Copyright © 2011-2022 走看看