zoukankan      html  css  js  c++  java
  • dp之多重背包poj1276

    题意:有现今cash,和n种钱币,每种钱币有ni个,价值为di,求各种钱币组成的不超过cash的最大钱数.......

    思路:二进制拆分转化为01背包,或者转化为完全背包都是可以的。

    反思:这个题目我wa两次,是应为我把判断cash==0||n==0放得太前,以致于后面的数据木有输入

    wa代码:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[110000],t[30000],s[2000][2];
    int main()
    {
        int cash,n;
        while(scanf("%d%d",&cash,&n)>0)
        {
             if(cash==0||n==0)               //错在这里,放的太前 
             {
                   printf("0
    ");
                   continue;
             }
             int cnt=0;
             for(int i=1;i<=n;i++)
             {
                     scanf("%d%d",&s[i][0],&s[i][1]);
                     int k=1;
                     while(s[i][0]-k>0)
                     {
                            t[cnt++]=k*s[i][1];
                            s[i][0]-=k;
                            k*=2;
                     }
                     t[cnt++]=s[i][0]*s[i][1];
             }
             memset(dp,0,sizeof(dp));
             for(int i=0;i<cnt;i++)
             {
                     for(int j=cash;j>=t[i];j--)
                     if(dp[j]<dp[j-t[i]]+t[i])
                     dp[j]=dp[j-t[i]]+t[i];
             }
             printf("%d
    ",dp[cash]);
        }
        return 0;
    }
    

     ac代码,二进制拆分:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[110000],t[30000],s[2000][2];
    int main()
    {
        int cash,n;
        while(scanf("%d%d",&cash,&n)>0)
        {
             int cnt=0;
             //memset(t,0,sizeof(t));
             for(int i=1;i<=n;i++)
             {
                     scanf("%d%d",&s[i][0],&s[i][1]);
                     int k=1;
                     if(s[i][0]==0||s[i][1]==0)
                     continue;
                     while(s[i][0]-k>0)
                     {
                            t[cnt++]=k*s[i][1];
                            s[i][0]-=k;
                            k*=2;
                     }
                     t[cnt++]=s[i][0]*s[i][1];
             }
             memset(dp,0,sizeof(dp));
             for(int i=0;i<cnt;i++)
             {
                     for(int j=cash;j>=t[i];j--)
                     if(dp[j]<dp[j-t[i]]+t[i])
                     dp[j]=dp[j-t[i]]+t[i];
             }
             printf("%d
    ",dp[cash]);
        }
        return 0;
    }
    

     ac代码,转换为完全背包:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    int dp[110000],num[100100],s[2000][2];
    int main()
    {
        int cash,n;
        while(scanf("%d%d",&cash,&n)>0)
        {
             int cnt=0;
             for(int i=1;i<=n;i++)
             {
                     scanf("%d%d",&s[i][0],&s[i][1]);
             }
             memset(dp,0,sizeof(dp));
             for(int i=1;i<=n;i++)
             {
                     memset(num,0,sizeof(num));
                     for(int j=s[i][1];j<=cash;j++)
                     if(dp[j]<dp[j-s[i][1]]+s[i][1]&&num[j-s[i][1]]<s[i][0])
                     {
                            dp[j]=dp[j-s[i][1]]+s[i][1];
                            num[j]=num[j-s[i][1]]+1;
                     }
             }
             printf("%d
    ",dp[cash]);
        }
        return 0;
    }
    
  • 相关阅读:
    操作系统复习目录
    leetcode Trapping Rain Water
    leetcode First Missing Positive
    leetcode Combination Sum II
    leetcode Word Search 待解决?
    [HDU] 1074 Doing Homework (NP性质的DP,远没有过去的自己写得好了)
    [HDU] 4513 吉哥系列故事——完美队形II
    [HDU] 4512 吉哥系列故事——完美队形I(有点dp味道的递归模拟)
    [HDU] 4519 郑厂长系列故事——体检
    [HDU] 4527 小明系列故事——玩转十滴水
  • 原文地址:https://www.cnblogs.com/ziyi--caolu/p/3216827.html
Copyright © 2011-2022 走看看