标签:end class -- tle dfs tmp scanf main 状态压缩
题意:n个点 m条边的图,路径价值定义为相邻点乘积,若路路径c[i-1]c[i]c[i+1]中c[i-1]-c[i+1]有边 则价值加上三点乘积
找到价值最大的哈密顿回路,和相应的方法数n<=13.
暴力dfs O(13!) TLE
由于n<13 经典的状态压缩dp [状态] [当前点位置 ][前一点位置] 注意上一个状态必须合法才能进行转移
设状态dp[s][i][j] 当前状态为s,当前点为i上一个点为j的最大价值, ans=max(dp[(1<<n)-1][i])
dp[s][i][j]= S=s^(1<<(i-1))&&dp[S][j][k]状态合法 max(dp[S][j][k]+v[j]*v[k]+v[i]*v[j]*v[k] (c[k],c[i]存在边))
O(2^13*13^3)
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N=1<<14;
ll n,m,v[15],g[15][15];
ll dp[N][15][15],path[N][15][15];
int main()
{
int q;
scanf("%d",&q);
while(q--)
{
memset(dp,-1,sizeof(dp));
memset(g,0,sizeof(g));
memset(path,0,sizeof(path));
scanf("%I64d%I64d",&n,&m);
for(int i=0;i<n;i++)
scanf("%I64d",&v[i]);
int u,V;
while(m--)
{
scanf("%d%d",&u,&V);
u--,V--;
g[u][V]=g[V][u]=1;
}
if(n==1)
{
cout<<v[0]<<‘ ‘<<1<<endl;
continue;
}
//3?ê??ˉ?àáúá?μ??·??dp?μ
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==j) continue;
if(g[i][j])
{
dp[(1<<i)+(1<<j)][i][j]=v[i]+v[j]+v[i]*v[j];
path[(1<<i)+(1<<j)][i][j]=1;
}
}
}
for(int s=0;s<(1<<n);s++)
{
for(int i=0;i<n;i++)
{
if(s&(1<<i)==0) continue;
for(int j=0;j<n;j++)
{
if(j==i||g[i][j]==0) continue;
if((s&(1<<j))==0) continue;
for(int k=0;k<n;k++)
{
if(j==k||((s&(1<<k))==0)||g[j][k]==0) continue;
int add=v[i]+v[i]*v[j];
if(g[i][k])
add+=v[i]*v[j]*v[k];
int S=s^(1<<i);
if(dp[S][j][k]==-1) continue;//?°ò???×′ì?òao?·¨
int tmp=dp[S][j][k]+add;
if(tmp>dp[s][i][j])
dp[s][i][j]=tmp,path[s][i][j]=path[S][j][k];
else if(tmp==dp[s][i][j])
path[s][i][j]+=path[S][j][k];
}
}
}
}
ll ans=-1,cnt=0;
ll s=(1<<n)-1;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==j) continue;
if(ans<dp[s][i][j])
ans=dp[s][i][j],cnt=path[s][i][j];
else if(ans==dp[s][i][j])
cnt+=path[s][i][j];
}
}
if(ans==-1)
ans=0,cnt=0;
cout<<ans<<‘ ‘<<cnt/2<<endl;
}
return 0;
}
POJ 2288 Islands And Bridges 状态压缩dp+哈密顿回路
标签:end class -- tle dfs tmp scanf main 状态压缩
原文地址:http://www.cnblogs.com/HIKARI1149/p/7044691.html