您的位置:首页 > 其它

POJ 2288 Islands and Bridges(状压DP->多种限制条件的TSP)

2017-11-08 11:55 513 查看
Islands and Bridges
Time Limit:4000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

Given a map of islands and bridges that connect these islands, a Hamilton path, as we all know, is a path along the bridges such that it visits each island exactly once. On our map, there is also a positive integer value associated
with each island. We call a Hamilton path the best triangular Hamilton path if it maximizes the value described below. 

Suppose there are n islands. The value of a Hamilton path C1C2...Cn is calculated as the sum of three parts. Let Vi be the value for the island Ci. As the first part, we sum over all the Vi values for each island in the path. For the second part, for each edge
CiCi+1 in the path, we add the product Vi*Vi+1. And for the third part, whenever three consecutive islands CiCi+1Ci+2 in the path forms a triangle in the map, i.e. there is a bridge between Ci and Ci+2, we add the product Vi*Vi+1*Vi+2. 

Most likely but not necessarily, the best triangular Hamilton path you are going to find contains many triangles. It is quite possible that there might be more than one best triangular Hamilton paths; your second task is to find the number of such paths. 

Input 

The input file starts with a number q (q<=20) on the first line, which is the number of test cases. Each test case starts with a line with two integers n and m, which are the number of islands and the number of bridges in the map, respectively. The next line
contains n positive integers, the i-th number being the Vi value of island i. Each value is no more than 100. The following m lines are in the form x y, which indicates there is a (two way) bridge between island x and island y. Islands are numbered from 1
to n. You may assume there will be no more than 13 islands. 

Input

The input file starts with a number q (q<=20) on the first line, which is the number of test cases. Each test case starts with a line with two integers n and m, which are the number of islands and the number of bridges in the map, respectively. The next line
contains n positive integers, the i-th number being the Vi value of island i. Each value is no more than 100. The following m lines are in the form x y, which indicates there is a (two way) bridge between island x and island y. Islands are numbered from 1
to n. You may assume there will be no more than 13 islands. 

Output

For each test case, output a line with two numbers, separated by a space. The first number is the maximum value of a best triangular Hamilton path; the second number should be the number of different best triangular Hamilton paths. If the test case does not
contain a Hamilton path, the output must be `0 0'. 

Note: A path may be written down in the reversed order. We still think it is the same path. 

Sample Input

2
3 3
2 2 2
1 2
2 3
3 1
4 6
1 2 3 4
1 2
1 3
1 4
2 3
2 4
3 4


Sample Output

22 3
69 1



哈密顿回路

编辑词条

该词条缺少词条分类,补充相关内容帮助词条更加完善!立刻编辑>>



哈密顿回路(2)

   天文学家哈密顿(William Rowan Hamilton) 提出,在一个有多个城市的地图网络中,寻找一条从给定的起点到给定的终点沿 途恰好经过所有其他城市一次的路径。

   这个问题和著名的过桥问题的不同之处在于,某些城市之间的旅行不一定是双向的。比如A→B,但B→A是不允许的。

   换一种说法,对于一个给定的网络,确定起点和终点后,如果存在一条路径,穿过这个网络,我们就说这个网络存在哈密顿路径。

哈密顿路径问题在上世纪七十年代初,终于被证明是“NP完备”的。据说具有这样性质的问题,难于找到一个有效的算法。实际上对于某些顶点数不到100的网络,利用现有最好的算法和计算机也需要比较荒唐的时间(比如几百年)才能确定其是否存在一条这样的路径。

  从图中的任意一点出发,路途中经过图中每一个结点当且仅当一次,则成为哈密顿回路。

  要满足两个条件:

  1.封闭的环

  2.是一个连通图,且图中任意两点可达

  经过图(有向图无向图)中所有顶点一次且仅一次的通路称为哈密顿通路。

  经过图中所有顶点一次且仅一次的回路称为哈密顿回路。

  具有哈密顿回路的图称为哈密顿图,具有哈密顿通路但不具有哈密顿回路的图称为半哈密顿图。

  平凡图是哈密顿图。

题意:求一条哈密顿回路,但是权值计算不同,包括三部分:1经过个所有点的权值相加。2经过的连续两个点的权值的乘积。3,能够构成三角型的连续三个点的乘积。这些全部加起来就是这条回路的总权值。输出最大权值和这个最大权值的路线有多少条。

这题很难构造DP方程,因为题目中要加上构成三角形的乘积,所以用三维dp[state][i][j],state是当前状态,i,j是相邻的两条边,用这两条边去更新新的状态因为三维可以在更新时就判断是否满足三角形减少了下个状态时的判断,,

虽然模板是TSP但是还是很复杂的,数据量开long long

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

using namespace std;

const int N = 14;

typedef long long LL;

LL  dp[1<<N]

, road[1<<N]

, v
, s

;

int main()

{

    int t;

    scanf("%d", &t);

    while(t--)

    {

        int n, m;

        scanf("%d %d", &n, &m);

        memset(dp,-1,sizeof(dp));

        memset(road,0,sizeof(road));

        memset(s,0,sizeof(s));

        for(int i=1;i<=n;i++)

            scanf("%d", &v[i]);

        for(int i=0;i<m;i++)

        {

            LL x, y;

            scanf("%lld %lld", &x, &y);

            s[x][y]=s[y][x]=1;

        }

        if(n==1)

        {

            printf("%lld 1\n",v[1]);

            continue;

        }

        int num=(1<<n);

        for(int i=1;i<=n;i++)

        {

            for(int j=1;j<=n;j++)

            {

                if(i!=j&&s[i][j])

                {

                    int state=1<<(i-1);

                    state|=(1<<(j-1));

                    dp[state][i][j]=v[i]+v[j]+v[i]*v[j];

                    road[state][i][j]=1;

                }

            }

        }

        for(int now=0;now<num;now++)

        {

            for(int i=1;i<=n;i++)

            {

                if(!(now&(1<<(i-1))))

                    continue;

                for(int j=1;j<=n;j++)

                {

                    if(!(now&(1<<(j-1)))||s[i][j]==0||i==j)

                        continue;

                    if(dp[now][i][j]==-1)

                        continue;

                    for(int k=1;k<=n;k++)

                    {

                        if(now&(1<<(k-1)))

                            continue;

                        if(s[j][k]==0||i==k||j==k)

                            continue;

                        int sum=dp[now][i][j]+v[k]+v[j]*v[k];

                        if(s[i][k])

                            sum+=(v[i]*v[j]*v[k]);

                        int state=now|(1<<(k-1));

                        if(dp[state][j][k]<sum)

                        {

                            dp[state][j][k]=sum;

                            road[state][j][k]=road[now][i][j];

                        }

                        else if(dp[state][j][k]==sum)

                        {

                            road[state][j][k]+=road[now][i][j];

                        }

                    }

                }

            }

        }

        LL ans=0, cnt=0;

        for(int i=1;i<=n;i++)

        {

            for(int j=1;j<=n;j++)

            {

                if(i==j||s[i][j]==0||dp[num-1][i][j]==-1)

                    continue;

                else if(dp[num-1][i][j]>ans)

                {

                    ans=dp[num-1][i][j];

                    cnt=road[num-1][i][j];

                }

                else if(dp[num-1][i][j]==ans)

                {

                    cnt+=road[num-1][i][j];

                }

            }

        }

        printf("%lld %lld\n",ans,cnt/2);

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: