NOWCODER 郊区春游(Floyd算法+状压DP)

链接:https://ac.nowcoder.com/acm/problem/16122
来源:牛客网在这里插入图片描述
在这里插入图片描述
题意:
  给n个点和m条路径和R个必经点,求经过这R个必经点的最短路径长度

思路:
  状压DP,套个模板先,下次再补(下次也不一定)

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
ll n,m,R,dis[209][209],r[20],a,b,c,dp[20][1<<15],ans=inf;
int main() {
	cin>>n>>m>>R;
	for(int i=1; i<=R; i++) cin>>r[i];//需要去玩耍的郊区编号
	for(int i=1; i<=n; i++) {
		for (int j=1; j<=n; j++) {
			if (i!=j)  dis[i][j]=inf;
		}
	}
	for(int i=1; i<=m; i++) {
		cin>>a>>b>>c;
		dis[b][a]=dis[a][b]=min(dis[a][b],c); //表示a到b的最短路径
	}
	//Floyd求最短路
	for(int k=1; k<=n; k++) {
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=n; j++) {
				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
			}
		}
	}
	//初始化dp数组
	memset(dp,0x3f,sizeof(dp));
	for(int i=1; i<=R; i++) dp[i][1<<(i - 1)] = 0;//从第i个地点开始时花费为0
	for(int s=1; s<(1<<R)-1; s++) { //表示去过的地点二进制集合的十进制表示
		for(int i=1; i<=R; i++) {
			if(s & (1<<(i-1))) {//s的二进制的第i位为1,即已经去了第i个地点
				//那么我们就可用当前的数据去更新还未去的地点的数据
				for(int j=1; j<=R; j++) {
					if((s & (1<<(j-1)))==0) {//s的二进制的第j位为0,即第j个地点没有去过
						dp[j][s+(1<<(j-1))]=min(dp[j][s+(1<<(j-1))],dp[i][s]+dis[r[i]][r[j]]);
						//dp[i][j]表示当前在i地点,已经访问过结点集合为j,所经过路径的最小花费
					}
				}
			}
		}
	}
	for (int i=1; i<=R; i++) {
		ans = min(ans,dp[i][(1<<R)-1]);
	}
	cout<<ans<<endl;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值