hdu 3001(状态压缩dp)

点击打开链接


题意:

有n个城市,m条路,每个城市最多走两次,求走完全部城市的最小路程。。。


因为没个城市最多走两次,所以要用3进制,求出1<<10的所有状态,并且此状态中每个城市走的次数。

状态方程dp[i+t3[k]][k]=max(dp[i][j]+map[j][k]);

dp[i][j]表示在状态i时走到j的最短路程。。。。



#include"stdio.h"
#include"string.h"
#define N 11
#define inf 0x1f1f1f1f
int state[60000][N];
int dp[60000][N];
int map[N][N];
int t3[N];
int top,n;
void init()
{
	int i,j;
	top=0;
	for(i=0;i<60000;i++)
	{
		int t=i;
		for(j=0;j<10;j++)
		{
			state[i][j]=t%3;
			t/=3;
		}
	}
	t3[0]=1;
	for(i=1;i<N;i++)
		t3[i]=t3[i-1]*3;
}
int min(int a,int b)
{
	return a<b?a:b;
}
int main()
{
	int m;
	int i,j,k;
	init();
	while(scanf("%d%d",&n,&m)!=-1)
	{	
		memset(map,inf,sizeof(map));
		memset(dp,inf,sizeof(dp));
		while(m--)
		{
			scanf("%d%d%d",&i,&j,&k);
			i--;j--;
			if(map[i][j]>k)map[i][j]=map[j][i]=k;
		}
		for(i=0;i<n;i++)dp[t3[i]][i]=0;
		int ans=inf;
		for(i=0;i<t3[n];i++)
		{
			int f=1;
			for(j=0;j<n;j++)
			{
				if(state[i][j]==0)f=0;
				if(dp[i][j]==inf)continue;
				for(k=0;k<n;k++)
				{
					if(j==k)continue;
					if(state[i][k]>=2)continue;			
					if(map[j][k]==inf)continue;
					dp[i+t3[k]][k]=min(dp[i][j]+map[j][k],dp[i+t3[k]][k]);
				}
			}
			if(f==1)
			{
				for(j=0;j<n;j++)
					ans=min(ans,dp[i][j]);
			}
		}
		if(ans>=inf)ans=-1;
		printf("%d\n",ans);
	}
	return 0;
}






你可能感兴趣的:(HDU,状态压缩dp)