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\n");

               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\n",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\n",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\n",dp[cash]);

    }

    return 0;

}

 

你可能感兴趣的:(poj)