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 }
  • 相关阅读:
    hdu2328 Corporate Identity
    hdu1238 Substrings
    hdu4300 Clairewd’s message
    hdu3336 Count the string
    hdu2597 Simpsons’ Hidden Talents
    poj3080 Blue Jeans
    poj2752 Seek the Name, Seek the Fame
    poj2406 Power Strings
    hust1010 The Minimum Length
    hdu1358 Period
  • 原文地址:https://www.cnblogs.com/djfuuxjz/p/11832168.html
Copyright © 2011-2022 走看看