Vijos P1002 过河 (NOIP提高组2005)

链接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; }



posted @ 2017-04-17 17:14  brucemengbm  阅读(177)  评论(0编辑  收藏  举报