多重部分和问题
Time Limit: 10000 ms Memory Limit: 256 MB
Total Submission: 40 Submission Accepted: 17
Total Submission: 40 Submission Accepted: 17
Description
有n种不同大小的数字,每种各个。判断是否可以从这些数字之中选出若干使它们的和恰好为K。
Input
首先是一个正整数T(1<=T<=100)
接下来是T组数据
每组数据第一行是一个正整数n(1<=n<=100),表示有n种不同大小的数字
第二行是n个不同大小的正整数ai(1<=ai<=100000)
第三行是n个正整数mi(1<=mi<=100000),表示每种数字有mi个
第四行是一个正整数K(1<=K<=100000)
接下来是T组数据
每组数据第一行是一个正整数n(1<=n<=100),表示有n种不同大小的数字
第二行是n个不同大小的正整数ai(1<=ai<=100000)
第三行是n个正整数mi(1<=mi<=100000),表示每种数字有mi个
第四行是一个正整数K(1<=K<=100000)
Output
对于每组数据,如果能从这些数字中选出若干使它们的和恰好为K,则输出“Yes”,否则输出“No”,每个输出单独占一行
Sample Input
Original | Transformed |
2 3 3 5 8 3 2 2 17 2 1 2 1 1 4
Sample Output
Original | Transformed |
Yes No
Source
安徽省2015年“京胜杯”大学生程序设计竞赛
题目大意:中文题目。
题目分析:就是一个多重背包的问题,然后做这题得到的一个感觉就是,做dp题,就是应该用dp的思路去求解。最外层循环数字的种类,内层循环数字。dp【i+1】【j】代表 组成数字j后第i种数字还剩下的个数。然后就有以下几种情况:
一: 前i-1种数字已经可以组成数字j了,所以此时第i种数字还剩下m【i】个,没有使用。
二: 前i种数字组成j-a【i】已经不剩余了,或者a【i】大于j
三:其他情况。
代码一:这是用二维数组的
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int a[maxn],m[maxn];
int dp[100][100005];
int main(){
int t;
cin>>t;
while(t--){
memset(dp,-1,sizeof(dp));
int n,k;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>m[i];
cin>>k;
dp[1][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=k;j++){
if(dp[i][j] >= 0)
dp[i+1][j] = m[i];
else if(dp[i+1][j-a[i]] <= 0 || j < a[i] )
dp[i+1][j] = -1;
else dp[i+1][j] = dp[i+1][j-a[i]] - 1;
}
}
if(dp[n+1][k]>=0)
cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
代码二:这是用一维数组的
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int a[maxn],m[maxn];
int dp[100005];
int main(){
int t;
cin>>t;
while(t--){
memset(dp,-1,sizeof(dp));
int n,k;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>m[i];
cin>>k;
dp[0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=k;j++){
if(dp[j] >= 0)
dp[j] = m[i];
else if(dp[j-a[i]] <= 0 || j < a[i] )
dp[j] = -1;
else dp[j] = dp[j-a[i]] - 1;
}
}
if(dp[k]>=0)
cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}