zoukankan      html  css  js  c++  java
  • Vijos 1002 过河

         这是我写的在Vijos上的第一题。这道题在我刚学完DP的时候,就做过。当时年少轻狂,没有看数据的范围,直接暴力DP,结果TLE。。。。后来就没有再碰过。知道最近觉得快要省赛了,有必要把原来没有做出来的题做一做,于是有了这篇博客。

        从那时学完的最简单的动规后,又学了一个名叫状压DP的算法,状压即状态压缩,把没有用的状态全部排除掉。BZOJ上就有一道状压DP的题(互不侵犯king)传送门!!而过河这道题就是一道状压DP。根据我现在的习惯,做题先看数据范围,然后判定算法。(1 <= L <= 10^9)这么大的数,根据经验应该用log级的算法,但是再看题目显然用不到任何log级的算法。而应该是DP。那么既然是DP又有这么大的数据范围,所以应该是状压DP。这样算法就判断出来了。那么该怎么压缩呢?这里要用到一个定理

    Px+(P+1)y=Q     

          x,y是未知数,P是跳跃的距离,P+1也是跳跃的距离,对于任意Q,Q>=P*(P-1), x,y一定存在正整数解,换句话说当两个石子之间的距离大于等于T*(T-1)时,中间有相当大的距离是每个点都可以跳到的,因为没有石子,所以对答案没有贡献,可以取模(%90),这样就很好办了。。。于是我们就成功地把状态给压缩了。

    注意:石子并没有按顺序给出要排序。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define inf 1<<30
    using namespace std;
    int l,s,t,m,f[900000],pos[200],a[900000];
    void slove(){
        int ans=0;
        for(int i=1;i<=m;i++)
            if(pos[i]%s==0) ans++;
        printf("%d",ans);
    }
    int main()
    {
        scanf("%d%d%d%d",&l,&s,&t,&m);
        for(int i=1;i<=m;i++)
            scanf("%d",&pos[i]);
        sort(pos+1,pos+m+1);
        if(s==t){
            slove();
            return 0;
        }
        for(int i=1;i<=m;i++){
            int temp=pos[i]-pos[i-1];
            pos[i]=pos[i-1]+temp%90;
        }
        l=pos[m]+(l-pos[m])%90;
        for(int i=1;i<=m;i++)
            a[pos[i]]=1;
        for(int i=1;i<=l;i++)
            f[i]=inf;
        f[0]=0; 
        for(int i=1;i<=l;i++)
            for(int j=s;j<=t;j++)
                if(i-j>=0)
                    f[i]=min(f[i-j]+a[i],f[i]);
        printf("%d",f[l]);
    }
  • 相关阅读:
    Eclipse
    文件递归查找
    BeanFactory 和 AppliactionContext的区别?
    文件上传
    Servlet路径的使用
    FileInputStream和FileOutputStream文件复制
    CentOS 7安装Nginx
    C语言程序设计100例之(6):数字反转
    C语言程序设计100例之(5):分解质因数
    C语言程序设计100例之(4):水仙花数
  • 原文地址:https://www.cnblogs.com/xtx1999/p/4823073.html
Copyright © 2011-2022 走看看