卧薪尝胆,厚积薄发。
Shanghai2004 Islands and Bridges
Date: Tue Sep 04 11:41:58 CST 2018 In Category: NoCategory

Description:

一条哈密顿回路的价值由三部分组成:
$1$ 、所有点权值和之和。
$2$ 、相邻点权值乘积。
$3$ 、构成三元环的三个相邻点权值乘积。
求最大权值哈密顿路径。
$1\le n \le 13$

Solution:

状压 $DP$ 求哈密顿回路,注意 $long\ long$ 不能用 $\%d$ 输出。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int testcases;
#define MAXN 14
int n,m;
typedef long long ll;
ll f[1 << MAXN][MAXN][MAXN];
ll g[1 << MAXN][MAXN][MAXN];
ll val[MAXN];
int p[MAXN][MAXN];
void work()
{
memset(f,0xc0,sizeof(f));
memset(g,0,sizeof(g));
f[0][0][0] = 0;
memset(p,0,sizeof(p));
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;++i)scanf("%lld",&val[i]);
int a,b;
for(int i = 1;i <= m;++i)
{
scanf("%d%d",&a,&b);
p[a][b] = p[b][a] = 1;
}
if(n == 1)
{
printf("%lld %d\n",val[1],1);
return;
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
if(i != j && p[i][j] != 0)
{
f[(1 << (i - 1)) | (1 << (j - 1))][i][j] = val[i] + val[j] + val[i] * val[j];
g[(1 << (i - 1)) | (1 << (j - 1))][i][j] = 1;
}
}
}
int tot = (1 << n) - 1;
for(int b = 1;b <= tot;++b)
{
for(int i = 1;i <= n;++i)
{
if((b & (1 << (i - 1))) == 0)continue;
for(int j = 1;j <= n;++j)
{
if((b & (1 << (j - 1))) == 0)continue;
if(i == j || p[i][j] == 0)continue;
if(g[b][i][j] == 0)continue;
for(int k = 1;k <= n;++k)
{
if(b & (1 << (k - 1)))continue;
if(p[j][k] == 0)continue;
if(f[b | (1 << (k - 1))][j][k] < f[b][i][j] + val[k] + val[j] * val[k] + (p[i][k] ? val[i] * val[j] * val[k] : 0))
{
f[b | (1 << (k - 1))][j][k] = f[b][i][j] + val[k] + val[j] * val[k] + (p[i][k] ? val[i] * val[j] * val[k] : 0);
g[b | (1 << (k - 1))][j][k] = g[b][i][j];
}
else if(f[b | (1 << (k - 1))][j][k] == f[b][i][j] + val[k] + val[j] * val[k] + (p[i][k] ? val[i] * val[j] * val[k] : 0))
{
g[b | (1 << (k - 1))][j][k] += g[b][i][j];
}
}
}
}
}
ll ans1 = 0,ans2 = 0;
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
if(i == j || p[i][j] == 0)continue;
if(f[tot][i][j] > ans1)
{
ans1 = f[tot][i][j];
ans2 = g[tot][i][j];
}
else if(f[tot][i][j] == ans1)
{
ans2 += g[tot][i][j];
}
}
}
printf("%lld %lld\n",ans1,ans2 / 2);
}
int main()
{
scanf("%d",&testcases);
while(testcases--)work();
return 0;
}
In tag: DP-状压DP
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡