现在的位置: 首页 > 综合 > 正文

zoj 3001

2013年06月30日 ⁄ 综合 ⁄ 共 1324字 ⁄ 字号 评论关闭

题意:你要去旅行,要经过n个点,每个点最多经过两次,每一条路径有一定的消费,求最小消费。

状态设定很简单。dp[i][j],表示i状态下j是最后到达的城市,不过最多经过两次所以要用三进制的状态0表示不经过,1表示经过一次,2表示经过两次。边界条件显然是开始出发的城市设定为0。接着状态转移就好了,注意预处理,要对每个数的三进制的位置的值处理一下。

Run ID Submit Time Judge Status Pro.ID Exe.Time Exe.Memory Code Len. Language Author
4486291 2011-08-24 20:23:33 Accepted 3001 546MS 5372K 1316 B G++ xym2010
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int dig[11]={1,3,9,27,81,243,729,2187,6561,19683,59049};
int bit[59050][11],dp[59050][11],n,m,gp[11][11],maxn[11];
void init()
{
	int j;
	for(int i=0;i<dig[10];i++)
	{
		int tem=i;
		for(j=0;tem;j++)
		{
			bit[i][j]=tem%3;
			tem/=3;
		}
	}
}
void DP()
{
	memset(dp,0x1f1f1f1f,sizeof(dp));
	for(int i=0;i<n;i++)
		dp[dig[i]][i]=0;
	int ans=0x1f1f1f1f,flag=1;
	for(int i=0;i<dig[n];i++)
	{
		flag=1;
		for(int j=0;j<n;j++)
		{
			if(bit[i][j]==0)
			{
				flag=0;
				continue;
			}
			for(int k=0;k<n;k++)
			{
				if(j==k||bit[i][k]==0)continue;
				int tem=i-dig[j];
				if(dp[tem][k]==0x1f1f1f1f||gp[k][j]==-1)continue;
				dp[i][j]=min(dp[i][j],dp[tem][k]+gp[k][j]);
			}
		}		
		if(flag==1)
		for(int j=0;j<n;j++)
		if(dp[i][j]!=0x1f1f1f1f)
		{
			ans=min(ans,dp[i][j]);
		}
	}
	if(ans==0x1f1f1f1f)
		printf("-1\n");
	else
	    printf("%d\n",ans);
}
int main()
{
	int x,y,w;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		
		memset(gp,-1,sizeof(gp));
		init();
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&x,&y,&w);
			if(gp[x-1][y-1]==-1||gp[x-1][y-1]>w)
			gp[x-1][y-1]=gp[y-1][x-1]=w;
		}
		DP();
	}
	return 0;
}


抱歉!评论已关闭.