Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) |
题意:类TSP问题每个点最多走两次
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
int MIN(int a,int b){
return a<b?a:b;
}
int state[15];
int map[15][15];
int dp[60000][15];
int dig[60000][15];
void init(){
state[1]=1;
for(int i=2;i<12;++i){
state[i]=state[i-1]*3;
}
for(int i=1;i<=state[11];++i){//将该状态变换为三进制;
int n=i,k=1;
while(n){
dig[i][k++]=n%3;
n/=3;
}
}
}
int main()
{
init();
int i,j,k,n,m;
while(scanf("%d%d",&n,&m)!=EOF){
memset(dp,0x3f,sizeof(dp));
memset(map,0x3f,sizeof(map));
for(i=1;i<=m;++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(map[a][b]>c){
map[a][b]=map[b][a]=c;
}
}
for(i=1;i<=n;++i)
dp[state[i]][i]=0;//确定起点
int ans=inf;
for(int s=state[1];s<state[n+1];++s){//枚举各种状态;
int flag=1;
for(i=1;i<=n;++i){
if(dig[s][i]==0)flag=0;//判断是否经过该点
if(dp[s][i]==inf)continue;
for(j=1;j<=n;++j){
if(i==j)continue;
if(map[i][j]==inf||dig[s][j]==2)continue;//如若不能通行或经过该地超过两次
int news=s+state[j];//更新
dp[news][j]=MIN(dp[news][j],dp[s][i]+map[i][j]);
}
}
if(flag){//如果该状态下所有点都经过过更新最小花费;
for(j=1;j<=n;++j){
ans=MIN(ans,dp[s][j]);
}
}
}
if(ans==inf)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}