poj 2288 tsp经典问题

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

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int maxn = 13;
typedef long long int ll_int;

ll_int dp[maxn][maxn][1<<maxn];
ll_int way[maxn][maxn][1<<maxn];
int G[maxn][maxn];
int V[maxn];

int main()
{
   freopen("E:\\acm\\input.txt","r",stdin);
    int T;
    cin>>T;
    while(T--){
        int n,m;
        cin>>n>>m;
        memset(G,0,sizeof(G));
        memset(dp,0,sizeof(dp));
        memset(way,0,sizeof(way));
        for(int i=0;i<n;i++)  cin>>V[i];
        for(int i=0;i<m;i++){
            int x,y;
            cin>>x>>y;
            G[x-1][y-1] = 1;
            G[y-1][x-1] = 1;
        }
        if(n == 1){
            printf("%d 1\n",V[0]);
            continue;
        }
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++){
                if(G[i][j]){
                    dp[i][j][(1<<i)|(1<<j)] = V[i] + V[j] + V[i]*V[j];
                    dp[j][i][(1<<i)|(1<<j)] = V[i] + V[j] + V[i]*V[j]; //先处理相邻的两点的;
                    way[i][j][(1<<i)|(1<<j)] = 1;
                    way[j][i][(1<<i)|(1<<j)] = 1;
                }
            }
        int All = (1<<n) - 1;
        for(int S = 3;S <= All; S++){  //在每个状态下枚举状态内的点i,j,扩展出节点k.挺暴力的。
            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]) continue;
                    for(int k=0;k<n;k++){
                        if((1<<k)&S || !G[j][k])    continue;
                        int r = S + (1<<k);
                        ll_int q = dp[i][j][S] + V[k] + V[j]*V[k];
                        if(G[i][k]){
                            q += V[i]*V[j]*V[k];
                        }
                        if(q > dp[j][k][r]){
                            dp[j][k][r] = q;
                            way[j][k][r] = way[i][j][S];
                        }
                        else if(q == dp[j][k][r]){
                            way[j][k][r] += way[i][j][S];
                        }
                    }
                }
            }
        }
        ll_int ans,answay;
        ans = 0; answay = 0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++){
               if(i!=j){
                  if(dp[i][j][All] > ans){
                     ans = dp[i][j][All];
                     answay = way[i][j][All];
                  }
                  else if(dp[i][j][All] == ans ){
                     answay += way[i][j][All];
                  }
               }
        }
        if(ans == 0)  printf("0 0\n");
        else
            printf("%I64d %I64d\n",ans,answay/2);

    }
}
View Code

 

posted @ 2013-09-02 23:19  等待最好的两个人  阅读(230)  评论(0编辑  收藏  举报