洛谷 P1052 [NOIP2005 提高组] 过河(dp,数学)

传送门


解题思路

很巧妙的一个题。
朴素的dp方程肯定都能列出来,关键是离散化如何操作。
可以仿照NOIP2017D1T1小凯的疑惑,将两个石头之间距离>=(st-s-t)全部转化为(st-s-t)。
可以理解为若距离>=(st-s-t),则所有的点都能到达。
但是这题要求宽松,方便又保险起见,把距离限度设置为s
t也可以稳过。

AC代码

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
#include<ctime>
#include<stack>
using namespace std;
const int maxn=2e6+5;
int n,m,s,t,l,a[maxn],d[maxn],vis[maxn],ans=1e5,dp[maxn];
int main()
{
	ios::sync_with_stdio(false);
	memset(dp,0x3f,sizeof(dp));
	dp[0]=0;
	cin>>l>>s>>t>>m;
	for(int i=1;i<=m;i++) cin>>a[i];
	sort(a+1,a+m+1);
	if(s==t){
		int cnt=0;
		for(int i=1;i<=m;i++) if(a[i]%s==0) cnt++;
		cout<<cnt;
		return 0;
	}
    for(int i=1;i<=m;i++){
    	if(a[i]-a[i-1]>s*t) d[i]=d[i-1]+s*t;
    	else d[i]=d[i-1]+a[i]-a[i-1];
    	vis[d[i]]=1;
	}
	n=s*t*m+t;
	for(int i=1;i<=n;i++){
		for(int j=s;j<=t;j++){
			if(i>=j) dp[i]=min(dp[i],dp[i-j]+vis[i]);
		}
		if(i>=d[m]) ans=min(ans,dp[i]);
	}
	cout<<ans;
    return 0;
}

//NOIP2005提高组 t2

posted @ 2021-08-01 10:57  尹昱钦  阅读(138)  评论(0编辑  收藏  举报