标签:mod bool 直接 class 最小 青蛙跳 blog 问题 names
https://www.vijos.org/p/1002
分析:很容易想到f[i]=min(f[i],f[i-j]+is_stone[i])的递推式,但L高达10^9,很明显会TLE,我们发现m<= 100,在长达1到10^9的线段里就只有100个点这是多么的稀疏,我们看看有什么方法压缩一下,引用:
问题的关键就是多么长的空地才能保证青蛙对这些空地是处处可达的?假设这个距离是X,
那么比X长的空地也都是处处可达的,就与长为X的空地等效了,因此这就是压缩长度的关键。
最后的结论是X=T^2。青蛙跳跃X需要跳T次T长度,但是可以把每个T逐个换成S(也就是T-1)
那么TS到TT就是跳T次能到达的所有格子了。而跳T-1次能到达的最大长度为(T-1)T=ST,
与跳T次的最小长度衔接上了。而T的最大值是10,也就是X取100。
因此先对输入数据进行一次初始化,如果发现两个石子之间的长度比100大,那么就直接视为它们相距100即可。
a[i]=a[i-1]+(a[i]-a[i-1])%90;即可压缩
#include<iostream> #include<algorithm> #include<cstring> using namespace std; const int maxm=110,mod=100,maxn=100010,inf=999999999; int L,s,t,m,a[maxm],f[maxn]; bool book[maxn]; int main(){ cin>>L>>s>>t>>m; for(int i=1;i<=m;++i)cin>>a[i]; sort(a+1,a+1+m); if(s==t){ int ans=0; for(int i=1;i<=m;++i){ if(a[i]%s==0)++ans; } cout<<ans; return 0; } //压缩 for(int i=1;i<=m;++i){ int dis=a[i]-a[i-1]; a[i]=dis%mod+a[i-1]; } L=a[m]; for(int i=1;i<=m;++i){ book[a[i]]=1; } f[0]=0; for(int i=1;i<=L+t;++i){ f[i]=inf; for(int j=s;j<=t;++j){ if(i-j<0)break; f[i]=min(f[i],f[i-j]+book[i]); } } int ans=inf; for(int i=L;i<=L+t;++i){ ans=min(ans,f[i]); } cout<<ans; return 0; }
标签:mod bool 直接 class 最小 青蛙跳 blog 问题 names
原文地址:http://www.cnblogs.com/Dream-Runner/p/7364586.html