题目链接: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;
}