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;
    }
    
  • 相关阅读:
    求逆序对的解法
    关于宽搜BFS广度优先搜索的那点事
    大数乘法 poj2389
    二分求幂(快速求幂,二进制求幂)
    2n皇后问题
    poj2406 Power Strings (kmp 求最小循环字串)
    poj1050查找最大子矩阵和
    二叉树的建立和遍历
    已知二叉树前序和中序,求二叉树。
    c/c++连接mysql数据库设置及乱码问题(vs2013连接mysql数据库,使用Mysql API操作数据库)
  • 原文地址:https://www.cnblogs.com/ziyi--caolu/p/3216827.html
Copyright © 2011-2022 走看看