洛谷 P1052 [NOIP2005 提高组] 过河(dp,数学)
传送门
解题思路
很巧妙的一个题。
朴素的dp方程肯定都能列出来,关键是离散化如何操作。
可以仿照NOIP2017D1T1小凯的疑惑,将两个石头之间距离>=(st-s-t)全部转化为(st-s-t)。
可以理解为若距离>=(st-s-t),则所有的点都能到达。
但是这题要求宽松,方便又保险起见,把距离限度设置为st也可以稳过。
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