题意:一个去旅行,要求花费最小走完所有的城市,可以选择任意一个城市出发,有个限制条件,每个城市最多能走两次。。
如果只用2进制表示,只能表示这个城市走过没有,所以我想不到做法。。
正确的做法是用3进制,每一位就可以表示走过这个城市的次数(2次以上也算做两次),所以先事先处理出没有3进制能表示的状态,然后枚举这些状态,如果这个状态中存在一个城市为0,就代表这个状态不行(flag=0)。。
/*************************************************************************
> File Name: 3001.cpp
> Author: tjw
> Mail:
> Created Time: 2014年11月10日 星期一 17时54分08秒
************************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define ll long long
#define ls k<<1
#define rs k<<1|1
using namespace std;
const int MAXN=600000;
const int INF=1<<30;
int bit[11]={1,3,9,27,81,243,729,2187,6561,19683,59049};
int dp[MAXN][12];
int num[MAXN][12];
int mp[10][10];
void init()
{
int i,j;
for(i=0;i<bit[10];i++)
{
int temp=i;
for(j=0;j<10;j++)
{
num[i][j]=temp%3;
temp=temp/3;
}
}
}
int main()
{
int n,m,u,v,c,i,j,k;
init();
while(scanf("%d%d",&n,&m)==2)
{
memset(mp,-1,sizeof(mp));
while(m--)
{
scanf("%d%d%d",&u,&v,&c);
u--;
v--;
if(mp[u][v]==-1||mp[u][v]>c)
mp[u][v]=mp[v][u]=c;
}
for(i=0;i<bit[n];i++)
{
for(j=0;j<n;j++)
dp[i][j]=INF;
}
for(i=0;i<n;i++)
dp[bit[i]][i]=0;
int ans=INF;
for(i=0;i<bit[n];i++)
{
int flag=1;
for(j=0;j<n;j++)
{
if(num[i][j]==0)
flag=0;
if(dp[i][j]==INF)
continue;
for(k=0;k<n;k++)
{
if(mp[j][k]==-1||j==k||num[i][k]>=2)
continue;
int temp=i+bit[k];
dp[temp][k]=min(dp[temp][k],dp[i][j]+mp[j][k]);
}
}
if(flag)
{
for(j=0;j<n;j++)
ans=min(ans,dp[i][j]);
}
}
if(ans==INF)
ans=-1;
printf("%d\n",ans);
}
return 0;
}

本文介绍了一种使用3进制动态规划解决旅行商问题的方法,通过枚举所有可能的状态并利用3进制来记录每个城市被访问的次数,以此达到在特定约束条件下寻找最优路径的目的。
8658

被折叠的 条评论
为什么被折叠?



