poj 2288 (MST) #by nobody

来源:互联网 发布:macbook pro 删除软件 编辑:程序博客网 时间:2024/05/16 04:06

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


题意:

哈密尔顿路问题。n个点,每一个点有权值,设哈密尔顿路为 C1C2...Cn,Ci的权值为Vi,一条哈密尔顿路的值分为三部分计算:
1.每一个点的权值之和
2.对于图中的每一条CiCi+1,加上Vi*Vi+1
3.对于路径中的连续三个点:CiCi+1Ci+2,若在图中,三点构成三角形,则要加上Vi*Vi+1*Vi+2
求一条汉密尔顿路可以获得的最大值,并且还要输出有多少条这样的哈密尔顿路。


看的别人的解答。http://www.cnblogs.com/chasetheexcellence/archive/2012/04/17/poj2288.html


附上代码:


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define MAXN 13
#define MAXS (1<<MAXN | 1)
typedef long long LL;


int dp[MAXN][MAXN][MAXS];
LL way[MAXN][MAXN][MAXS];
int map[MAXN][MAXN],v[MAXN];
int n,m,S;


int main()
{
    //freopen("input.txt","r",stdin);
    int cases;
    scanf("%d",&cases);
    while(cases--)
    {
        memset(map,0,sizeof(map));
        memset(dp,-1,sizeof(dp));
        memset(way,0,sizeof(way));
        scanf("%d%d",&n,&m);
        S = 1<<n;


        for(int i=0;i<n;i++)
            scanf("%d",&v[i]);
        for(int i=0;i<m;i++)
        {
            int v1,v2;
            scanf("%d%d",&v1,&v2);
            map[v1-1][v2-1] = map[v2-1][v1-1] = 1;
        }
        if(n==1){printf("%d %d\n",v[0],1);continue;}
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(map[i][j])
                {
                    dp[i][j][1<<i | 1<<j] = v[i] + v[j] + v[i]*v[j];
                    way[i][j][1<<i | 1<<j] = 1;
                }
        for(int s=3;s<S;s++)
        {
            for(int i=0;i<n;i++)
            {
                if(!((1<<i)&s))continue;
                for(int j=0;j<n;j++)
                {
                    if(!((1<<j)&s) || i==j || dp[i][j][s] == -1)continue;
                    for(int k=0;k<n;k++)
                    {
                        if(!map[j][k] || (1<<k)&s )continue;
                        int temp = dp[i][j][s]+v[k]+v[k]*v[j];


                        if(map[i][k])temp += v[i]*v[j]*v[k];
                        int ns = s|(1<<k);
                        if(dp[j][k][ns] < temp)
                        {
                            dp[j][k][ns] = temp;
                            way[j][k][ns] = way[i][j][s];
                        }
                        else if(dp[j][k][ns] == temp)
                        {
                            way[j][k][ns] += way[i][j][s];
                        }
                    }
                }


            }
        }


        int ansv=0;
        LL answ=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                if(i==j)continue;
                if(ansv < dp[i][j][S-1])
                {
                    ansv  = dp[i][j][S-1];
                    answ = way[i][j][S-1];
                }
                else if(ansv == dp[i][j][S-1])
                {
                    answ += way[i][j][S-1];
                }
            }
        printf("%d %I64d\n",ansv,answ/2);


    }
    return 0;
}