dp之混合背包poj1742(推荐)

题意:给你价值为a1,a2.....的货币,每种有c1,c2.......个,求这些货币所能组成的价值小于等于m有多少个.....

思路:很像一道多重背包题?那我一开始的确是用多重背包的思路编写的......TLE了,原来其中隐藏着一个被我忽视的一个问题,当ai*ci>=m时,我们没有必要去拆分ci了,就直接把这种情况当作完全背包处理.......

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[100005],t[300][2];
int n,m;
int sum;
void deal1(int x)
{
        for(int j=m;j>=x;j--)
        if(dp[j-x]&&dp[j-x]+x>dp[j]&&dp[j-x]+x-1<=m)
        {
                if(!dp[j])   sum++;
                dp[j]=dp[j-x]+x;
        }
}
int main()
{
      
      while(scanf("%d%d",&n,&m)>0&&(n+m))
      {
           for(int i=1;i<=n;i++)
           {
                   scanf("%d",&t[i][0]);
           }
           memset(dp,0,sizeof(dp));
           dp[0]=1;
           sum=0;
           for(int i=1;i<=n;i++)
           {
                   scanf("%d",&t[i][1]);
                   if(t[i][1]*t[i][0]<m)
                   {
                        int k=1;
                        while(t[i][1]-k>0)
                        {
                            deal1(k*t[i][0]);
                            t[i][1]-=k;
                            k*=2;
                        }
                        deal1(t[i][1]*t[i][0]);
                    }
                    else
                    {
                        for(int j=t[i][0];j<=m;j++)
                        if(dp[j-t[i][0]]&&dp[j]<dp[j-t[i][0]]+t[i][0])
                        {
                            if(!dp[j])   sum++;
                            dp[j]=dp[j-t[i][0]]+t[i][0];
                        } 
                    }
           }
           printf("%d\n",sum);
      }
      return 0;
}

 

posted @ 2013-07-29 14:42  紫忆  阅读(1370)  评论(0编辑  收藏  举报