误操作害死人。。。。。。
题意:一只青蛙,在0--L上从0开始跳,每次可以跳[s,t]的距离
给出一些石子的坐标,问从0跳到(跳过L)最少踩几颗石子
这是DP啊
好不容易想到
以f[i]代表跳到i时最少踩的石子数
然而 正当happy之时
TM数据范围$huge{L<=10^9!!!}$
。。。。。。。
后来看了题解
发现自己的思路是对的
L的范围太大,无法作为数组下标,所以先离散化,再DP。
两点间的距离d大于t时,一定可以由d%t跳过来,
所以最多只需要t+d%t种距离的状态就可以表示这两个石子之间的任意距离关系。
这样就把题目中的10^9压缩成了2*t*m最多不超过2000,
然后就可以放心大胆地用DP了。
不过要注意题目中的“当青蛙跳到或跳过坐标为L的点时,
就算青蛙已经跳出了独木桥”,所以DP的终点是一个范围而非确切的一个点,
最后还要在这个范围内取最小值。
#include<cstdio> #include<iostream> #include<algorithm> #include<cctype> #include<cstring> using namespace std; #define int long long int l,s,t; int x[200]; int m; int v[20500]; int f[20500]; int cnt; int ans; inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-f; ch=getchar(); } while(isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } inline void put(int x) { if(x<0) { putchar('-'); x=-x; } if(x>9) put(x/10); putchar(x%10+'0'); } signed main() { l=read(); s=read(); t=read(); m=read(); memset(f,0x7f,sizeof f); for(int i=1;i<=m;i++) x[i]=read(); x[m+1]=l; sort(x+1,x+m+2); for(int i=1;i<=m+1;i++) { if(x[i]-x[i-1]>=t) cnt+=(x[i]-x[i-1])%t+t; else cnt+=x[i]-x[i-1]; v[cnt]=true; } v[cnt]=0; v[0]=0; f[0]=0; for(int i=1;i<=cnt+t-1;i++) { for(int j=s;j<=t;j++) if(i>=j) f[i]=min(f[i-j]+v[i],f[i]); } ans=0x7fffffff; for(int i=cnt;i<=cnt+t-1;i++) ans=min(ans,f[i]); put(ans); return 0; }