zoukankan      html  css  js  c++  java
  • 01背包 + 排序 (记忆化搜索) 骄傲的商人(HDU

    01背包 + 排序

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3466

    题目大意:n中商品,m元钱,每种商品都有p,q,v属性,p价格,q表示买这种商品你需要带q元老板才愿意和你交易,v这种商品的实际价值,求问最多可以获得多少价值。

    这题是有先决条件的dp,会导致没达到限制条件的 j 在 i+1 后达到,但没法正确更新,没法直接解决这个问题,就要用到排序解决。                       

    比如对于第二个样例,第一件商品 5 10 5只会把dp[10]更新出来,但实际上花费了5,更新第二个商品时,需要dp[10]=max(dp[10-5]+6,dp[10]),此时需要借助上一层的dp[5],但实际上此时dp[5]还没有更新。

    发现先不管价值v,如果有 5 10 和 10 12 的两件商品,那么要想全部买下,顺序会影响需要的钱。  分别需要的钱为 Q2+P1 = 17 和 Q1+P2 = 20,肯定选需要钱少的那个Qx+Py  ,即先买y ,  当Q2+P1 > Q1+P2 , 可以化为 Q2-P2 > Q1-P1 , 即 Qx - Px 大的先考虑买不买

    并且,这个抉择要用记忆化搜索 dfs 才能直接模拟,如果用循环迭代,则要倒过来循环,也可以直接排序,按照 Qx + Py 从小打大的顺序。

    记忆化搜索写法:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int dp[555][5555];
     7 int N,M;
     8 typedef struct{
     9     int q,p,v;
    10 }node;
    11 node a[555];
    12 bool cmp(node a,node b){
    13     return a.q-a.p>b.q-b.p;
    14 }
    15 int DP(int i,int j){   
    16     if(dp[i][j]>=0) return dp[i][j];
    17     int res;
    18     if(i==N) return 0;
    19     
    20     else if(j<a[i].q){
    21         res=DP(i+1,j);
    22     }
    23     else{
    24           res=max(DP(i+1,j),DP(i+1,j-a[i].p)+a[i].v);    
    25     }
    26     return dp[i][j]=res;
    27 }
    28 
    29 int main(){
    30     while(scanf("%d%d",&N,&M)!=EOF){
    31         memset(dp,-1,sizeof(dp));
    32 //        memset(dp,0,sizeof(dp));
    33         for(int i=0;i<N;i++){
    34             scanf("%d%d%d",&a[i].p,&a[i].q,&a[i].v);
    35         }
    36         sort(a,a+N,cmp);
    37 //        for(int i=0;i<N;i++){
    38 //            for(int j=0;j<=M;j++){
    39 //                if(j<a[i].q) 
    40 //                  dp[i+1][j]=dp[i][j];
    41 //                else 
    42 //                  dp[i+1][j]=max(dp[i][j-a[i].p]+a[i].v,dp[i][j]);
    43 //            }
    44 //        }
    45         printf("%d
    ",DP(0,M));
    46     }
    47 }
    View Code

    迭代写法:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    int dp[555][5555];
    int N,M;
    typedef struct{
        int q,p,v;
    }node;
    node a[555];
    bool cmp(node a,node b){
        return a.q-a.p<b.q-b.p;
    }
    //int DP(int i,int j){   
    //    if(dp[i][j]>=0) return dp[i][j];
    //    int res;
    //    if(i==N) return 0;
    //    
    //    else if(j<a[i].q){
    //        res=DP(i+1,j);
    //    }
    //    else{
    //          res=max(DP(i+1,j),DP(i+1,j-a[i].p)+a[i].v);    
    //    }
    //    return dp[i][j]=res;
    //}
    
    int main(){
        while(scanf("%d%d",&N,&M)!=EOF){
    //        memset(dp,-1,sizeof(dp));
            memset(dp,0,sizeof(dp));
            for(int i=0;i<N;i++){
                scanf("%d%d%d",&a[i].p,&a[i].q,&a[i].v);
            }
            sort(a,a+N,cmp);
            for(int i=0;i<N;i++){
                for(int j=0;j<=M;j++){
                    if(j<a[i].q) 
                      dp[i+1][j]=dp[i][j];
                    else 
                      dp[i+1][j]=max(dp[i][j-a[i].p]+a[i].v,dp[i][j]);
                }
            }
            printf("%d
    ",dp[N][M]);
        }
    }
    View Code
  • 相关阅读:
    费用流入门
    网络最大流入门
    假期编程
    假期编程
    假期编程
    假期编程
    假期编程
    假期编程
    假期编程
    假期编程
  • 原文地址:https://www.cnblogs.com/-Zzz-/p/11409490.html
Copyright © 2011-2022 走看看