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;
    }
    
  • 相关阅读:
    .net开发微信公众号(2)-验证服务器地址
    [广度遍历和深度遍历]聊聊算法和设计模式
    DDD领域驱动设计之聚合、实体、值对象
    DDD领域驱动设计之运用层代码
    DDD领域驱动设计之领域服务
    DDD领域驱动设计之领域基础设施层
    DDD领域驱动设计实践篇之如何提取模型
    Docker最全教程——从理论到实战(七)
    Docker最全教程——从理论到实战(六)
    Docker最全教程——从理论到实战(五)
  • 原文地址:https://www.cnblogs.com/ziyi--caolu/p/3216827.html
Copyright © 2011-2022 走看看