zoukankan      html  css  js  c++  java
  • 20191110noip2014飞扬的小鸟~ | 背包dp(完全背包)(01背包)

    luogu1941飞扬的小鸟

    不得不说出这题的人太强了!!!此题结合了01背包、完全背包以及各种细节!!!

    题意:

    一张图长n高m,有k个关卡,每个关卡只能从l+1到h-1间通过,小鸟从位置0的任意高度出发,对于每一个位置i,点击一下可以上升xi的高度,每个位置可以点击无数次,但是如果不点击,就会下降yi的高度,达到顶部m不能继续向上但合法,降到底部0为非法,求若能通关的最小点击次数,若不能通关,求能通过的最大关卡数

    dp题解:

    f[i][j]表示达到i,j位置时的最小点击数,初始时除了f[0][1~m]=0,都为无限大

    完全背包:

    因为一个位置i可以点击无数次,所以上升的操作就是一个完全背包

    f[i][j] = min(f[i - 1][j - x[i]] + 1,f[i][j - x[i]] + 1)

    01背包:

    因为不操作只能下降y[i],所以下降操作是01背包

    f[i][j] = min(f[i][j],f[i - 1][j + y[i]])

    细节:

    如果达到m,对于m时的最小值,我们还要枚举m~m+x[i]中求最小

    给定通过关卡的高度范围为l~h但是由于不能卡着边过,所以范围要处理为l+1~h-1

    由于对边界有特殊的判断,所以数组下标范围要比m大一点

    时间复杂度:O(nm)

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 int x[11005],y[11005],high[11005],low[11005],f[11005][2005];//数组要稍微开大一点 
     6 bool vis[11005];
     7 int main()
     8 {
     9 //    freopen("1.in","r",stdin); 
    10     int n,m,k;
    11     scanf("%d%d%d",&n,&m,&k);
    12     for(int i =1;i <= n;i ++)
    13     {
    14         scanf("%d%d",&x[i],&y[i]); 
    15     }
    16     for(int i = 1;i <= n;i ++)
    17     {
    18         high[i] = m;
    19         low[i] = 1;
    20     }
    21     for(int i = 1,p,l,h;i <= k;i ++)
    22     {
    23         scanf("%d%d%d",&p,&l,&h);
    24         vis[p] = 1;
    25         high[p] = h - 1;
    26         low[p] = l + 1;
    27     }
    28     memset(f,0x3f,sizeof(f));
    29     for(int i = 1;i <= m;i ++)f[0][i] = 0;
    30     for(int i = 1;i <= n;i ++)
    31     {
    32         for(int j = x[i] + 1;j <= m + x[i];j ++)//上升是完全背包
    33         {
    34             f[i][j] = min(f[i - 1][j - x[i]] + 1,f[i][j - x[i]] + 1);
    35         }
    36         for(int j = m + 1;j <= m + x[i];j ++)
    37         {
    38             f[i][m] = min(f[i][m],f[i][j]);
    39         }
    40         for(int j = 1;j <= m - y[i];j ++)//下降是01背包
    41         {
    42             f[i][j] = min(f[i][j],f[i - 1][j + y[i]]); 
    43         }
    44         for(int j = 1;j <= low[i] - 1;j ++)f[i][j] = f[0][0];
    45         for(int j = high[i] + 1;j <= m;j ++)f[i][j] = f[0][0];    
    46     }
    47     int ans = f[0][0];
    48     for(int i = 1;i <= m;i ++)
    49     {
    50         ans = min(ans,f[n][i]);
    51     }
    52     if(ans < f[0][0])printf("1
    %d
    ",ans);
    53     else
    54     {
    55         int ans = 0;
    56         for(int i = 1;i <= n;i ++)
    57         {
    58             bool suc = 0;
    59             for(int j = 1;j <= m;j ++)
    60             {
    61                 if(f[i][j] < f[0][0])
    62                 {
    63                     suc = 1;
    64                     if(vis[i])ans++;
    65                     break;
    66                 }
    67             }
    68             if(!suc)break;
    69         }
    70         printf("0
    %d
    ",ans);
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    儿童节扣扣讲座心得
    leetcode -- Best Time to Buy and Sell Stock II
    leetcode -- Best Time to Buy and Sell Stock
    JDeveloper中文乱码问题
    Oracle BAM数据量限制64000解决办法
    记录一条纠结了SQL语句
    OEPE创建webservice出现的一些问题
    Oracle OSB [Security:090304]Authentication Failed
    ICommand简单用法
    Oracle BAM添加企业消息源实现数据的实时监控
  • 原文地址:https://www.cnblogs.com/djfuuxjz/p/11832168.html
Copyright © 2011-2022 走看看