题目链接:
题意:给出一幅图。图中有一些点,然后从第1个点出发,然后途径全部有石头的点。最后回到原点,然后求最小距离。当初作比赛的时候不知道这就是旅行商经典问题。回来学了一下。
思路:
状态转移方程
DP[k][i|base[k]]=min(DP[k][i|base[k]],DP[j][i]+dis[j][k])
DP[J][I]表示从起点到j点在i状态下的最小距离。。。DP[j][i]+dis[j][k]表从j到k的距离。。
。时间复杂度是(n?m+(t2)?(2t)),那么问题就得到了解决。。
题目:
3 3 0 0 0 0 100 0 0 0 0 2 2 1 1 1 1
4 4
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<cmath>
#include<string>
#include<queue>
#define eps 1e-9
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=10+5;
int dp[maxn][1<<maxn],dis[maxn][maxn],base[maxn];//dp[j][i]表示在i状态下到达j的最小距离
int p[maxn][2],n,m;
int cal(int i,int j)
{
return abs(p[i][0]-p[j][0])+abs(p[i][1]-p[j][1]);
}
int main()
{
int cnt,k;
while(~scanf("%d%d",&n,&m))
{
cnt=0;
base[1]=1;
for(int i=2;i<=14;i++)
base[i]=base[i-1]<<1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&k);
if(k||(i==1&&j==1))
{
p[++cnt][0]=i;
p[cnt][1]=j;
}
}
memset(dis,0,sizeof(dis));
for(int i=1;i<=cnt;i++)
for(int j=i+1;j<=cnt;j++)
dis[i][j]=dis[j][i]=cal(i,j);
memset(dp,INF,sizeof(dp));
dp[1][0]=0;
int lim=1<<cnt;
for(int i=0;i<lim;i++)//状态
for(int j=1;j<=cnt;j++)//j点为起点
{
if(dp[j][i]==INF) continue;
for(int k=1;k<=cnt;k++)//转移到的点
{
if(i&base[k]) continue;
dp[k][i|base[k]]=min(dp[k][i|base[k]],dp[j][i]+dis[j][k]);
}
}
printf("%d\n",dp[1][lim-1]);
}
return 0;
}
hdu5067Harry And Dig Machine(TSP旅行商问题)
原文:http://www.cnblogs.com/lcchuguo/p/5267866.html