• [NOIP2014] 飞扬的小鸟 【背包】


    题目

    很明显的背包问题,向上飞可以点无限次,所以是完全背包,向下掉只可能掉一次,所以是01背包。又因为不能在掉落之后再上升,所以要先算完全背包

    我开始用的是递推,75分(TLE5个点…),对于每一列能够到达的点,推出下一行所能到达的点(所以就重复计算了很多次,完全没有用到背包的思想)

    接着开始考虑背包,对于一列i的纵坐标j,f[i][j]表示到达这个点需要点击的最小次数,那么

    f[i][j]=min{f[i-1][j-up]+1,f[i][j-up]+1,f[i-1][j+down]};

    然后就是i,j到底应该在哪个范围内怎么取的问题了,特别傻逼的我认为j必须要大于这一列的下面那一根水管的高度,然后就开始了

    for(int i=1; i <= n; i++)
        for(int j=max(bottom[i],up[i]); j <= top[i]; j++)

    结果可想而知
    因为有可能前面几次点击屏幕的时候鸟还低于下面的水管,而如果这么算的话前面几次点击屏幕的就无法被记录到了,就有可能会无法通过水管(我被这东西卡了好久,然后赌运气把第二个循环的范围换了,结束之后再把无法到达的点初始化就A了…)

    还是有很多其他细节要处理的(感觉每次写NOIP的题都是跪在细节上)

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    const int N=10010, M=1010, inf=100000010;
    int n, m, k, flag=1;
    int f[N][M], pip[N], top[N], bot[N], up[N], down[N];
    
    int solve()
    {
        int flag1, ans1=0;
        for(int i=1; i <= n; i++)
        {
            flag1=0;
            for(int j=up[i]; j <= m; j++)
            {
                if(j == m)
                    for(int u=m-up[i]; u <= m; u++)
                    {
                        if(f[i][j] > f[i-1][u]+1) f[i][j]=f[i-1][u]+1;
                        if(f[i][j] > f[i][u]+1) f[i][j]=f[i][u]+1;
                    }
                if(f[i][j] > f[i-1][j-up[i]]+1) f[i][j]=f[i-1][j-up[i]]+1;
                if(f[i][j] > f[i][j-up[i]]+1) f[i][j]=f[i][j-up[i]]+1;
                if(f[i][j] != inf && j < top[i] && j > bot[i]) flag1=1;
            }
            for(int j=1; j <= m; j++){
                if(j+down[i] < top[i-1] && j+down[i] > bot[i-1] && f[i][j] > f[i-1][j+down[i]]) f[i][j]=f[i-1][j+down[i]];
                if(f[i][j] != inf && j < top[i] && j > bot[i]) flag1=1;
                //printf("%d %d %d %d %d %d %d
    ",i,j,bot[i],top[i],up[i],down[i],f[i][j]);
            }
            if(!flag1) {flag=0; return ans1;}
            for(int j=0; j <= bot[i]; j++) f[i][j]=inf;
            for(int j=top[i]; j <= m; j++) f[i][j]=inf;
            if(pip[i]) ans1++;
        }
        int ans=inf;
        for(int i=1; i <= m; i++) if(f[n][i] < ans) ans=f[n][i];
        return ans;
    }
    
    int read(){
        int out=0, f=1; char c=getchar(); while(c < '0' || c > '9') {if(c == '-') f=-1; c=getchar();}
        while(c >= '0' && c <= '9') {out=(out<<1)+(out<<3)+c-'0'; c=getchar();}
        return out*f;
    }
    
    void init()
    {
        //freopen("testdata.in","r",stdin);
        n=read(), m=read(), k=read();int x;
        for(int i=1; i <= n; i++) up[i]=read(), down[i]=read();
        for(int i=1; i <= k; i++)  x=read(), pip[x]=1, bot[x]=read(), top[x]=read();
        for(int i=0; i <= n; i++) if(!pip[i]) top[i]=m+1;
        for(int i=1; i <= n; i++)
            for(int j=0; j <= m; j++)
                f[i][j]=inf;
    }
    
    int main()
    {
        init();
        int ans=solve();
        printf("%d
    %d
    ", flag, ans);
        return 0;
    }
    
  • 相关阅读:
    java:输出流程printStream
    phalcon 连接多个数据库 phalcon multi-database
    Selenium Webdriver元素定位的八种常用方法
    adb push ,adb pull和adb install的区别
    Java将数据写进excel
    Java接口和抽象类的区别
    深入理解Java的接口和抽象类
    Java内存解析 程序的执行过程
    bit,byte,char,位,字节,字符 的区别
    java static成员变量方法和非static成员变量方法的区别 ( 二 )
  • 原文地址:https://www.cnblogs.com/zerolt/p/9260889.html
Copyright © 2020-2023  润新知