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;
}