zoukankan      html  css  js  c++  java
  • [P1941][NOIP2014T3] 飞扬的小鸟 (0/1背包+完全背包)

    题意:给出一张地图,有若干个竖直的管道,有一只鸟从地图最左边要飞到地图最右边,每次点击屏幕,小鸟就会上升,若不点击,小鸟就会下降;途中小鸟不能飞(掉)出地图,也不能碰到管道;

    求这一只鸟从地图最左边是否能飞到地图最右边,如果能,那么最小的点击次数是多少;

    解法:0/1背包+完全背包;

    1.0/1背包;当小鸟处在 (i,j)这个位置时,可以不点击屏幕;那么此时就是一个0/1背包;状态转移方程:f[i][j]=min(f[i-1][j-x[i]]+1,f[i][j-x[i]]+1);

    2.完全背包;当小鸟处在(i,j)这个位置时,可以点击多次屏幕;那么此时就是一个完全背包;状态转移方程:f[i][j]=min(f[i][j],f[i-1][j+y[i]]);

    有管道的地方可以  f[i][j]=inf;转移是从左到右,从下到上;

    附上代码:

    #include<iostream> 
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=10086;
    const int inf = 0x3f3f3f3f;
    
    inline int read(){
        int ref=0,x=1; char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')x=-1;ch=getchar();}
        while(isdigit(ch)){ref=ref*10+ch-'0';ch=getchar();}
        return ref*x;
    }
    
    int n,m,p;
    int x[N],y[N];
    int low[N],high[N],dp[N][2019];
    bool jud[N];
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&p);
        for(int i=1;i<=n;i++) x[i]=read(),y[i]=read();
        for(int i=1;i<=n;i++){
            low[i]=1;
            high[i]=m;
        }
        for(int i=1;i<=p;i++){
            int a,b,c;
            a=read(),b=read(),c=read();
            jud[a]=1;
            low[a]=b+1;
            high[a]=c-1;
        }
        memset(dp,0x3f3f3f,sizeof(dp));
        for(int i=1;i<=m;i++) dp[0][i]=0;
        for(int i=1;i<=n;i++){
            for(int j=x[i]+1;j<=m+x[i];j++) dp[i][j]=min(dp[i-1][j-x[i]]+1,dp[i][j-x[i]]+1);
            for(int j=1;j<=m-y[i];j++) dp[i][j]=min(dp[i][j],dp[i-1][j+y[i]]);
            for(int j=m+1;j<=m+x[i];j++) dp[i][m]=min(dp[i][m],dp[i][j]);
            for(int j=1;j<low[i];j++) dp[i][j]=inf;
            for(int j=high[i]+1;j<=m;j++) dp[i][j]=inf;
        }
        int ans=inf;
        for(int j=1;j<=m;j++) {
            ans=min(ans,dp[n][j]);
        }
        if(ans<inf) printf("1
    %d",ans);
        else{
            int place;
            bool ljw=false;
            for(int i=n-1;i>=1;i--) {
                for(int j=1;j<=m;j++){
                    if(dp[i][j]<inf){
                        place=i;
                        ljw=true;
                        break;
                    }
                }
                if(ljw) break;
            }
            ans=0;
            for(int i=1;i<=place;i++){
                if(jud[i]) ans++;
            }
            printf("0
    %d",ans);
        }
        return 0;
    }
  • 相关阅读:
    类与对象
    《大道至简》第三章读后感
    动手动脑及课后作业
    课程作业一
    第三周学习进度条
    软件工程个人作业02
    第二周学习进度条
    软件工程个人作业01(2)
    软件工程个人作业01
    登录界面
  • 原文地址:https://www.cnblogs.com/nnezgy/p/11371895.html
Copyright © 2011-2022 走看看