首页 > 其他 > 详细

vijos 1002 状压DP

时间:2019-12-13 00:22:17      阅读:137      评论:0      收藏:0      [点我收藏+]

题面

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。

题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

对于30%的数据,L <= 10000;
对于全部的数据,L <= 10^9。

格式

输入格式

输入的第一行有一个正整数L(1 <= L <= 10^9),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1 <= S <= T <= 10,1 <= M <= 100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

输出格式

输出只包括一个整数,表示青蛙过河最少需要踩到的石子数。

首先,对于前百分之30的数据,很容易想到状态转移方程:

f[i]=min(f[i],f[i-j])+(has_stone[i]?1:0);

也就是,从i-s到i-t之中找一个最小的走过来。最后如果当前位置是个石头,就+1

然后外层循环正着扫,内层循环循环上面的式子。时间O(kn)空间O(n)

但是,n实在是太大了。时间和空间都接受不了。

怎么办?

我们发现,石头的数量实在是太少了!只有100!

也就是说,会有大片的空地,青蛙在这片空地上瞎蹦跶了半天,而根本就没有必要!

T最大是10,也就是说,如果想要跳到某个石头上,一定是从石头左边最多10个位置跳过来的,同理,从石头左边跳,也就最多跳到石头右边十个的位置,在某两个石头中间(记为i,i+1),stone[i]+10到stone[i+1]-10,在这中间这一段里面蹦跶是没有意义的,因为一定踩不到石头,而无论怎么蹦跶,最后都要踩到左边10个和右边10个里面,因此如果两个石头间隔大于20,就直接视为20.这样一来,时空复杂度都只有O(MT)了

代码:

#include <cstdio>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define MAXN 214748364
int L,s,t,M,p;
int stone[101];
int has_stone[101*21+10];
int f[101*21+10];
int min(int a,int b){return a<b?a:b;}
void solve(){
    int ans=0;
    for(int i=1;i<=M;i++)
        if(stone[i]%s==0)
            ans++;
    printf("%d",ans);
    return;
}
int main(){
    scanf("%d%d%d%d",&L,&s,&t,&M);
    for(int i=1;i<=M;i++)
        scanf("%d",&stone[i]);
    if(s==t){
        solve();
        return 0;
    }
    sort(stone+1,stone+1+M);
    for(int i=1;i<=M;i++){
        p+=min(stone[i]-stone[i-1],20);
        has_stone[p]=1;
    }
    p+=min(L-stone[M],20);
    for(int i=1;i<=p+9;i++)f[i]=MAXN;
    for(int i=s;i<=p+9;i++){
        for(int j=s;j<=t;j++)
            f[i]=min(f[i],f[i-j]);
        if(has_stone[i])
            f[i]++;
    }
    int min_s=MAXN;
    for(int i=p;i<=p+9;i++)min_s=min(min_s,f[i]);
    printf("%d",min_s);
    system("pause");
    return 0;
}

 

 

vijos 1002 状压DP

原文:https://www.cnblogs.com/Zarax/p/12032629.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!