TSP问题

TSP问题最主要的特征,点数一般为16以为,然后每个点只能经过一次,求遍历所有点的最小代价

原始的TSP问题是要走一条回路的,即汉密尔顿回路,问题变形的话,可以不回到原点,也可以有多个原点

POJ 1699,把每个串看成一个点的话,就是求不指定原点的TSP问题,且不必回到原点(这题也可以AC自动机+最短路解决)

处理点与点之间的边权时需要用KMP预处理


HDU 3681,需要预处理F,G,Y这三种点之间的距离值,然后二分答案+利用TSP验证,由于G只能用一次,Y也只需到达一次,故可以用TSP解决

代码:

POJ 1699

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int n,dp[(1<<10)][11],next[25];
char str[12][25];
int g[11][11];
void get_next(int x)
{
	int i,j=0;
	next[1]=0;
	for(i=2;i<=strlen(str[x]+1);i++)
	{
		while(j>0&&str[x][i]!=str[x][j+1])
			j=next[j];
		if(str[x][i]==str[x][j+1])
			j++;
		next[i]=j;
	}
}
int cal(int x,int y)
{
	get_next(y);
	int i,j=0;
	for(i=1;i<=strlen(str[x]+1);i++)
	{
		while(j>0&&str[x][i]!=str[y][j+1])
			j=next[j];
		if(str[x][i]==str[y][j+1])
			j++;
	}
	return strlen(str[y]+1)-j;
}
int main()
{
	int i,j,k,T;
	scanf("%d",&T);
	while(T--)
	{
		memset(g,0,sizeof(g));
		scanf("%d",&n);
		for(i=0;idp[i][j]+g[j][k])
						{
							dp[ns][k]=dp[i][j]+g[j][k];
						}
					}
				}
			}
		}
		int ans=1<<30;
		for(i=0;i

hdu 3681

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct node 
{
	int x,y,step;
};
int g[16][16],n,m,id[16][16],kind[16],cnt,start,pos[16][2];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int dp[1<<16][16],vis[16][16],goal;
char mat[20][20];
bool in(int i,int j)
{
	if(i<1||j<1||i>n||j>m)
		return false;
	return true;
}
void bfs(int s)
{
	node now,next;
	queueque;
	now.x=pos[s][0]; now.y=pos[s][1];
	now.step=0;
	memset(vis,0,sizeof(vis));
	que.push(now);
	vis[now.x][now.y]=1;
	while(!que.empty())
	{
		now=que.front();
		que.pop();
		for(int i=0;i<4;i++)
		{
			int nx=now.x+dir[i][0];
			int ny=now.y+dir[i][1];
			if(!in(nx,ny)||mat[nx][ny]=='D')
				continue;
			if(vis[nx][ny])
				continue;
			vis[nx][ny]=1;
			next.x=nx; next.y=ny; next.step=now.step+1;
			if(mat[nx][ny]!='S')
			{
				g[s][id[nx][ny]]=now.step+1;
			}
			que.push(next);
		}
	}
}
bool check(int limit)
{
	memset(dp,-1,sizeof(dp));
	dp[1<=0)
				{
					dp[ns][k]=max(dp[ns][k],dp[i][j]-g[j][k]);
					if(kind[k]==1)
						dp[ns][k]=limit;
				}
			}
		}
	}
	return false;
}
void solve()
{
	int l=1,mid,r=n*m*8,ans=-1;
	goal=0;
	for(int i=0;i>1;
		if(check(mid))
		{
			ans=mid;
			r=mid-1;
		}
		else l=mid+1;
	}
	if(ans==-1)
		puts("-1");
	else	
		printf("%d\n",ans);
}
int main()
{
	int i,j,k;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		if(n+m==0)
			break;
		cnt=0;
		memset(g,0,sizeof(g));
		for(i=1;i<=n;i++)
		{
			scanf("%s",mat[i]+1);
			for(j=1;j<=m;j++)
			{
				if(mat[i][j]!='S'&&mat[i][j]!='D')
				{
					id[i][j]=cnt;
					if(mat[i][j]=='F')
					{
						kind[cnt]=0;
						start=cnt;
					}
					else if(mat[i][j]=='G')
					{
						kind[cnt]=1;
					}
					else 
					{
						kind[cnt]=2;
					}
					pos[cnt][0]=i; pos[cnt][1]=j;
					cnt++;
				}
			}
		}
		for(i=0;i



你可能感兴趣的:(动态规划)