链接:https://www.vijos.org/p/1002
解析:
若 p*x+(p+1)*y=Q(采用跳跃距离p和p+1时可以跳至任何位置Q),则在Q ≥ P*(P-1)时是一定有解的。
由于题目给出的一个区间是1≤S≤T≤10,于是当相邻的两个石子之间的距离不小于8*9=72时,则后面的距离都可以到达,我们就可以认为它们之间的距离就是72。如此一来,我们就将原题L的范围缩小为了100*72=7200,动态规划算法完全可以承受了。
但是当S=T时,上述等式是无法使用的,在这种情况下,只需要在所有石子中,统计出坐标是S倍数的石子个数就可以了。
注意:
1.运用DP的时候,需要压缩
2.特殊解答S==T的时候
代码:
#include <istream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define MIN(x,y) (x<y?x:y)
#define INF 1e7
int dp[100010];
int dd[100010];
int dis[105];
int main(){
int L,S,T,M;
int i,j;
scanf("%d%d%d%d", &L,&S,&T,&M);
for(i=1; i<=M; ++i)
scanf("%d", &dis[i]);
int ans = 0;
if(S==T){
for(i=1; i<M; ++i)
if(dis[i]%S == 0)
++ans;
}
else{
dis[0] = 0;
sort(dis, dis+M+1);
memset(dd, 0, sizeof(dd));
for(i=1,j=0; i<=M; ++i){
if((dis[i] - dis[i-1])>100)
j += 100;
else
j += dis[i]-dis[i-1];
dd[j] = 1;
}
int k = j+100;
dd[0] = 0;
for(i=1; i<=k; ++i){
dp[i] = INF;
for(j=S; j<=T; ++j){
if(i<j) break;
dp[i] = min(dp[i] , dp[i-j]+dd[i]);
}
}
ans = dp[k];
}
printf("%d\n", ans);
return 0;
}