P1052 [NOIP2005 提高组] 过河 (dp)

[NOIP2005 提高组] 过河 - 洛谷

题目描述

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,\cdots,L0,1,⋯,L(其中 LL 是桥的长度)。坐标为 00 的点表示桥的起点,坐标为 LL 的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是 SS 到 TT 之间的任意正整数(包括 S,TS,T)。当青蛙跳到或跳过坐标为 LL 的点时,就算青蛙已经跳出了独木桥。

题目给出独木桥的长度 LL,青蛙跳跃的距离范围 S,TS,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

输入格式

第一行有 11 个正整数 L(1\le L\le 10^9)L(1≤L≤109),表示独木桥的长度。

第二行有 33 个正整数 S,T,MS,T,M,分别表示青蛙一次跳跃的最小距离,最大距离及桥上石子的个数,其中 1\le S\le T\le101≤S≤T≤10,1\le M\le1001≤M≤100。

第三行有 MM 个不同的正整数分别表示这 MM 个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

输出格式

一个整数,表示青蛙过河最少需要踩到的石子数。

题解:

奇怪的dp。

因为桥太长了,又看到s,t,m都很小,那么考虑把两个石头距离太长的缩短,是可以证明对答案没影响的。那么缩短之后再写一个标记数组即可。

/*keep on going and never give up*/
#include
using namespace std;
#define int long long
#define endl '\n'
#define inf 1e15
#define fast std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=2e5+20;
int l,s,t,m,a[maxn],dp[maxn],d[maxn],f[maxn];
signed main(){
	fast
	cin>>l;cin>>s>>t>>m;
	if(s==t){
		int ans=0;
		for(int i=1;i<=m;i++){
			int k;cin>>k;
			if(k%s==0) ans++;
		}
		cout<>a[i];
	}
	sort(a+1,a+1+m);d[m+1]=min(l-a[m],100ll);
	int p=0;
	for(int i=1;i<=m;i++){
		d[i]=min(a[i]-a[i-1],100ll);p+=d[i];f[p]=1;
	}
	p+=d[m+1];int mi=1e14;
	for(int i=1;i<=p+10;i++){
			dp[i]=1e14;
		for(int j=s;j<=t;j++){
			if(i>=j) dp[i]=min(dp[i],dp[i-j]+f[i]);
		}
	}
	for(int i=p;i<=p+10;i++){
		mi=min(mi,dp[i]);
	}
	cout<

你可能感兴趣的:(ACM的日与夜,#,dp,#,思维题,动态规划,算法,贪心算法,c++,蓝桥杯)