HDU3001 Travelling 状压DP

哭瞎啊,每个城市可以经过至多两次,但没有要求必须经过两次,想用 两个状压来乱搞搞,结果自认为会T,结果 WA了,搞了一下午,没想到用三进制啊,智商捉急,参考了

http://blog.csdn.net/lenleaves/article/details/7980955  这个博客

每个城市可以经过1或2次,所以三进制可以代表所有状态了,接下来处理方式类似于二进制的,只是没有了位运算一些判断跟预处理有点繁琐

方程dp[s][i] = min(dp[s][i] ,  dp[s - (s除去j剩下状态)][k] + dis[k][j]),

由于没有固定的出发点,所以也就没有固定的终点,所以要以任何城市为终点的可能都要枚举到

dp[i][j]代表i状态下以 j为终点的最小花费

转移方程就是  : i  状态以j为终点的递推为(i状态中不经过j位置的状态下以k为终点 + k到j所需距离).


#define MAXN 0x3f3f3f3f

int n,m;

int dp[100000 + 55][10 + 5];

int mp[10 + 5][10 + 5];

int s[59050][10 + 5];

void clear() {
	
	for(int i=0;i<59050;i++) {
		int tmp = i;
		for(int j=1;j<=10;j++) {
			s[i][j] = tmp%3;
			tmp /= 3;
			if(!tmp)break;
		}
	}
}

void init() {
	memset(mp,0x3f3f3f3f,sizeof(mp));
	memset(dp,0x3f3f3f3f,sizeof(dp));
}

bool input() {
	while(scanf("%d %d",&n,&m) == 2) {
		for(int i=0;i<m;i++) {
			int u,v,val;
			scanf("%d %d %d",&u,&v,&val);
			if(val < mp[u][v]) {
				mp[u][v] = val;
				mp[v][u] = val;
			}
		}
		return false;
	}
	return true;
}

void cal() {
	if(n == 1) {puts("0");return ;}
	int now[12];
	now[0] = 0;
	now[1] = 1;
	for(int i=2;i<=11;i++)now[i] = 3 * now[i - 1];/*举出刚好只过i位置的状态*/
	for(int i=0;i<=n;i++)dp[now[i]][i] = 0;//边界值,只经过i位置的状态再以i为终点耗费肯定为0
	int ans = MAXN;
	for(int i=0;i<now[n + 1];i++) {
		bool flag = true;//标记判断是否访问了所有的地方
		for(int j=1;j<=n;j++) {/*枚举以j为终点*/
			if(s[i][j] == 0) {flag = false;continue;}//i状态并没有经过j
			for(int k=1;k<=n;k++) {
				if(s[i][k] == 0)continue;/*i状态没有经过k*/
				int tmp = i - now[j];//使得i状态中第j位置为0
				dp[i][j] = min(dp[i][j],dp[tmp][k] + mp[k][j]);
				/*i状态以j为终点的递推为(i状态中不过j位置的状态下以k为终点 + k到j所需距离)*/
			}
		}
		if(flag)//若该状态下所有地方都访问过了,就从以各个地方为终点的最佳方案中再取出最优的
			for(int j=1;j<=n;j++)ans = min(ans,dp[i][j]);
	}
	if(ans == MAXN)puts("-1");
	else printf("%d\n",ans);
}

void output() {

}

int main () {
	clear();
	while(true) {
		init();
		if(input())return 0;
		cal();
		output();
	}
	return 0;
}


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值