After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best choice!He has decided to visit n cities(he insists on seeing all the cities!And he does not mind which city being his start station because superman can bring him to any city at first but only once.), and of course there are m roads here,following a fee as usual.But Mr Acmer gets bored so easily that he doesn’t want to visit a city more than twice!And he is so mean that he wants to minimize the total fee!He is lazy you see.So he turns to you for help.
Input
There are several test cases,the first line is two intergers n(1<=n<=10) and m,which means he needs to visit n cities and there are m roads he can choose,then m lines follow,each line will include three intergers a,b and c(1<=a,b<=n),means there is a road between a and b and the cost is of course c.Input to the End Of File.
Output
Output the minimum fee that he should pay,or -1 if he can’t find such a route.
Sample Input
2 1
1 2 100
3 2
1 2 40
2 3 50
3 3
1 2 3
1 3 4
2 3 10
Sample Output
100
90
7
分析:
题意:
有n个城市和m条路,现在我们要遍历所有城市,问所走的最短路程是多少?(这道题有一个问题,那就是一个城市最多可以经过两次,这样就有点难了,但还是难不住大佬们,于是花了两个小时消化大佬的代码,一点一点写出了自己的,和大佬的差不多)。
解析:
首先,我们用三进制来表示每种情况,如:
三进制的121表示第一个城市去过一次了,第二个城市去过2次了,第三个城市去过了一次,通过三进制,我们很容易的表示每个城市的遍历情况,但是,我们是从哪个城市开始的,哪个城市结束的呢?对于这个问题,由于这里最多有10个城市,那么我们就把原来的一维变成二位,如:我们用数组dp[state][i]表示在state这种情况下,我们最后经历的哪个城市是i市的最短路程,最后我们只需要从遍历完所有城市的情况中找到最小值即可!
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define INF 0x3f3f3f3f
using namespace std;
int map[15][15];
int three[15];
int dp[N][15];
int list[N][15];
int main()
{
int n,m,a,b,len;
three[0]=1;
for(int i=1;i<=11;i++)
{
three[i]=three[i-1]*3;
}
for(int i=0;i<three[10];i++)
{
int val=i;
for(int j=1;j<=10&&val;j++)
{
list[i][j]=val%3;
val/=3;
}
}
while(~scanf("%d%d",&n,&m))
{
memset(map,INF,sizeof(map));
for(int i=0;i<three[n];i++)
{
for(int j=1;j<=n;j++)
{
dp[i][j]=INF;
}
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&len);
map[b][a]=map[a][b]=min(map[a][b],len);
}
for(int i=1;i<=n;i++)
{
dp[three[i-1]][i]=0;
}
int sum=INF;
for(int i=0;i<three[n];i++)
{
bool flag=true;
for(int j=1;j<=n;j++)
{
if(!list[i][j])
flag=false;
if(dp[i][j]!=INF)
{
for(int k=1;k<=n;k++)
{
if(map[j][k]!=INF&&list[i][k]!=2)
{
dp[i+three[k-1]][k]=min(dp[i][j]+map[j][k],dp[i+three[k-1]][k]);
}
}
}
}
if(flag)
{
for(int j=1;j<=n;j++)
{
sum=min(sum,dp[i][j]);
}
}
}
if(sum>=INF)
printf("-1\n");
else
printf("%d\n",sum);
}
return 0;
}