zoukankan      html  css  js  c++  java
  • HDU 2546 饭卡(带限制的01背包变形)

    思路:有几个解法,如下

    1)先拿出5块买最贵的菜,剩下的菜再进行01背包。如何证明正确性?设最贵的菜价e,次贵的菜价s,设减去5后的余额为x,会不会产生这样的情况,假设用5元买了e,余额最多能买到x-2钱的菜,那么共买到是x-2+e。而如果挑出s,并且有其他菜价组合加上e等于x呢?不知怎么证明。但是能AC,没有实现。

    2)将余额-5作为背包容量,进行01背包,dp时记录下每种背包容量中所不包含的最大菜价,这个菜最后用那5元来买。同样,不知道如何证明。

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 using namespace std;
     6 const int N=1005;
     7 int price[N];
     8 int raw[N];
     9 int dp[N];
    10 int mon, n;
    11 
    12 void cal()
    13 {
    14     sort(price,price+n); //先排序
    15     
    16     for(int i=0; i<n; i++)
    17     {
    18         if(mon-5>=price[i])
    19             for(int j=mon-5; j>=price[i]; j--)
    20             {
    21                 if(dp[j-price[i]]+price[i]>dp[j] )
    22                 {
    23                     dp[j]=dp[j-price[i]]+price[i];
    24                     raw[j]=raw[j-price[i]]; //记录最大的菜价
    25                 }
    26                 else
    27                     raw[j]=price[i];
    28             }
    29         else //为了防止余额连一个都买不上的情况
    30             for(int j=mon; j>0; j--)
    31                 raw[j]=price[i];
    32     }
    33     int ans=0;
    34     for(int i=1; i<=mon; i++) //扫出所有可能最大的组合
    35     {
    36         ans=max(dp[i]+raw[i],ans);
    37     }
    38     cout<<mon-ans<<endl;
    39 }
    40 
    41 
    42 int main()
    43 {
    44     //freopen("input.txt","r",stdin);
    45     while(cin>>n,n)
    46     {
    47         memset(raw, 0, sizeof(raw));
    48         memset(dp, 0, sizeof(dp));
    49         memset(price, 0, sizeof(price));
    50         
    51      
    52          for(int i=0; i<n; i++)
    53              scanf("%d", &price[i]);
    54          cin>>mon;
    55          if(mon<5)
    56          {
    57              cout<<mon<<endl;
    58              continue;
    59          }
    60          cal();
    61     }
    62     return 0;
    63 }
    AC代码(01背包)
  • 相关阅读:
    [luogu p1164] 小A点菜
    [luogu p5018] 对称二叉树
    [luogu p1305] 新二叉树
    [luogu p1030] 求先序排列
    [luogu p1087] FBI树
    [luogu p1449] 后缀表达式
    [luogu p1160] 队列安排
    [luogu p1057] 传球游戏
    有趣的问题系列-主元素问题
    [luogu p1192] 台阶问题
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4472755.html
Copyright © 2011-2022 走看看