题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001
题目大意:给你n个城市,m条路,问你把所有城市都走一遍,每个城市最多走两次的的最小花费。
解题思路:压缩状态成三进制,然后递推即可,注意三进制的表达,还有判断是否所有城市走一次的判断。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int dp[60000][12],tr[60000][12],map[12][12],sta[12];
int n,m;
void init()
{
memset(dp,inf,sizeof(dp));
memset(map,inf,sizeof(map));
for(int i=0;i<n;i++)
map[i][i]=0;
}
void Init()//3进制
{
sta[0]=1;
for(int i=1;i<=10;i++)
sta[i]=sta[i-1]*3;
for(int i=0;i<sta[10];i++)
{
int t=i;
for(int j=0;j<=10;j++)
{
tr[i][j]=t%3;
t/=3;
}
}
}
void solve()
{
int ans=inf;
for(int i=0; i<n; i++)
dp[sta[i]][i]=0; //初始化
for(int s=0; s<sta[n]; s++)
{
int flog =1;// 表示所有城市都走过至少一次
for(int i=0; i<n; i++)
{
if(tr[s][i]==0) flog=0; //有城市没走过
if(dp[s][i]==inf) continue;
for(int j=0; j<n; j++)
{
if( i==j || tr[s][j]==2 || map[i][j]==inf) continue;
int p=s+sta[j]; //s状态下 走过j城市得到 p状态
dp[p][j]=min(dp[p][j],dp[s][i]+map[i][j]);
}
}
if(flog)
for(int k=0;k<n;k++)
ans=min(ans,dp[s][k]);
}
if(ans==inf) printf("-1\n");
else printf("%d\n",ans);
}
int main()
{
Init();
while(~scanf("%d%d",&n,&m))
{
init();
int a,b,c;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
a--;b--;
if(map[a][b]>c) map[a][b]=map[b][a]=c;
}
solve();
}
return 0;
}