[POI 2004] MOS

一道很有意思的贪心题,似乎noi导刊上有?记不太清了,反正是做出来了。

题意

有一个桥,一个火把,一堆人。

这对人要过桥,过桥有一些条件。

  • 需要过桥的人有火把

  • 不可同时过两个以上

每次过桥的花费时间是两人中花费最高的那位。

询问最小的过桥花费。

注意,火把是必须有人带回的,这个火把不能凭空传送。

解法

这个其实并不难,我们发现 \(n\) 为 1, 2, 3 时的都很简单,我们从简单处入手。

对于 \(n=1\)

对于 \(n=2\)

对于 \(n=3\) 我们让最快的人分别带人过去再返回送火把,答案是所有人的花费之和。

但是对于 \(n>3\) 这个并不一定是正确的策略,我们但从这一次进行考虑这个确实是最优的,但是我们不能排除因为顺序而导致的不同。

比如有两个接近无限的数,这两个明显一起过更好,如果使用最快一个一个接明显不妥当。

所以我们多了一种策略,让最慢和次慢同行,显然最慢和次次慢更劣。

具体来讲第二种策略,我们让最快和次快先过,最快回来送火把,最慢和次慢过去,次快回来送火把。

这两种策略我们并不知道什么时候使用,所以直接 dp。

代码

#include <bits/stdc++.h>
using namespace std;
const int MN=1e6+116;
int n, a[MN], dp[MN];
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin>>n; for(int i=1; i<=n; ++i) cin>>a[i];
	dp[n]=a[n]+a[1];
	if(n==1){
		cout<<a[1]<<'\n';
		return 0;
	}
	for(int i=n-1; i; --i)
		dp[i]=min(a[i]+a[1]+dp[i+1],a[i+1]+a[2]+a[2]+a[1]+dp[i+2]);
	cout<<dp[3]+a[2]<<'\n';
	return 0;
}
posted @ 2025-09-21 19:37  BaiBaiShaFeng  阅读(2)  评论(0)    收藏  举报
Sakana Widget右下角定位