码迷,mamicode.com
首页 > 其他好文 > 详细

vijos 1002 过河

时间:2017-08-15 14:22:16      阅读:123      评论:0      收藏:0      [点我收藏+]

标签: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;
}

 

vijos 1002 过河

标签:mod   bool   直接   class   最小   青蛙跳   blog   问题   names   

原文地址:http://www.cnblogs.com/Dream-Runner/p/7364586.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!