NOIP2005过河(青蛙过河)
这道题主要是因为L长度最大可以为1e9 而石子却最多只有100个 这样就浪费了很多时间空间 所以我们压缩一波路径就可以了 剩余的就是枚举每个点以及i-y到i-x的dp了
这里要说一句为什么要mod90 因为1~9两两的最大公倍数是90
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=100007; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } int f[M],s[155],L,x,y,m,sz[M]; int main() { memset(f,127,sizeof(f)); L=read(); x=read(); y=read(); m=read(); for(int i=1;i<=m;i++) s[i]=read(); if(x==y){ int ans=0; for(int i=1;i<=m;i++) if(s[i]%x==0) ans++; printf("%d\n",ans); return 0; } s[m+1]=L; sort(s+1,s+m+2); for(int i=0;i<=m;i++) if(s[i+1]-s[i]>90) s[i+1]=s[i]+(s[i+1]-s[i])%90; for(int i=1;i<=m;i++) sz[s[i]]=1; for(int i=x;i<=y;i++) f[i]=(sz[i])?1:0; for(int i=2*x;i<=s[m+1];i++){ for(int j=x;j<=y;j++) if(j<=i) f[i]=min(f[i],f[i-j]); if(sz[i]) f[i]++; } printf("%d\n",f[s[m+1]]); return 0; }