poj 1742 Coins 多重背包---个人理解和做法

http://poj.org/problem?id=1742

大意:给你两个数字n和m,接下来有2n个数,分别代表n个数字以及n个数字对应的个数,问:用这些数字最多可以得到1~m中的多少的数字。

做法:一开始想强行来的,就是dp[i]表示数字i出现过没有,1表示出现0表示没出现,然后从m往1遍历,假如dp[i]为0并且dp[i-number]为1的话,结果就++,dp[i]=1;

这么做尽管用了二进制表示,但还是tle了

应该是dp[i][j]表示到了数字j可以剩下多少张数字i,然后用滚动1维数组代替二维数组。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m; 
int num[2][105],dp[100005];
int main(){
	while(scanf("%d %d",&n,&m),n||m){
		for(int i=1;i<=n;i++) scanf("%d",&num[0][i]);
		for(int i=1;i<=n;i++) scanf("%d",&num[1][i]);
		memset(dp,-1,sizeof(dp)); //不能设为0,0 代表还剩0张牌一样能到 
		dp[0]=num[1][1];
		int res=0;
		for(int i=1;i<=n;i++){
			for(int j=0;j<=m;j++){
				if(dp[j]>=0) dp[j]=num[1][i]; //滚动数组嘛。。。 
				else if(j>=num[0][i]&&dp[j-num[0][i]]>0){
					dp[j]=dp[j-num[0][i]]-1;   
					res++;
				} 
			}
		}
		cout<<res<<endl;
	}
	return 0; 
}

猜你喜欢

转载自blog.csdn.net/weixin_43191865/article/details/88726390