7-1 如何取得神之飞雪 最短路+dp (20分)

这篇博客探讨了一种结合贪心算法和动态规划的方法来解决带有重复边的最短路径问题以及一个特殊的01背包问题。在最短路径问题中,博主使用Dijkstra算法排除了重复边并处理了无穷远的情况。接着,针对不小于一定容量求最小价值的背包问题,博主应用了动态规划策略。最后,通过示例代码展示了如何找到在满足总容量至少为总和的三分之一的情况下,使总价值最小的物品组合。
摘要由CSDN通过智能技术生成

7-1 (20分)

在这里插入图片描述

考察:

贪心:最短路,考虑去重边,无穷远
dp:01背包,传统是不超过一定容量求最大价值,本题是不小于一定容量求最小价值。

#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f

const int N = 1010;
const int M = 2e6+10;
int a[N], v[N], n, m, s, sum;
ll ma[N][N], d[N], dp[M];

void dij(){
	d[s] = 0;
	for(int i = 1; i <= n; i++)
	{
		int x = 0;
		for(int j = 1; j <= n; j++)
			if(!v[j] && (x==0||d[j]<d[x])) x = j;
		v[x] = 1;
		for(int j = 1; j <= n; j++)
			d[j] = std::min(d[j], d[x]+ma[x][j]);
	}
}
int main(){
	scanf("%d%d%d", &n, &m, &s);
	for(int i = 1; i <= n; i++) 
	{
		scanf("%d", &a[i]);
		ma[i][i] = 0; sum += a[i];
		for(int j = i+1; j <= n; j++) ma[i][j] = ma[j][i] = inf;
	} 
	for(int i = 1; i <= m; i++)
	{
		int x, y; ll z;
		scanf("%d%d%lld", &x, &y, &z);
		ma[x][y] = ma[y][x] = std::min(ma[x][y], z);
	}
	for(int i = 1; i <= n; i++) d[i] = ma[s][i];
	dij();
	for(int i = 0; i <= sum; i++) dp[i] = inf;
	dp[0] = 0;
	for(int i = 1; i <= n; i++)
	{
		for(int j = sum; j >= a[i]; j--)
			dp[j] = std::min(dp[j], dp[j-a[i]]+d[i]); 
	} 		
	ll ans = inf;
	for(int i = sum/3+1; i <= sum; i++) ans = std::min(ans, dp[i]);
	if(ans == inf) printf("\"DIE TWICE.\"\n");
	else printf("%lld\n", ans);
	return 0;
} 
//别着急,慢点交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值