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; }
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。