4515: 又见背包
描述
有n种大小不同的数字 <nobr aria-hidden="true"> ai </nobr> <math xmlns="http://www.w3.org/1998/Math/MathML"> <msub> <mi> a </mi> <mi> i </mi> </msub> </math>,每种 <nobr aria-hidden="true"> mi </nobr> <math xmlns="http://www.w3.org/1998/Math/MathML"> <msub> <mi> m </mi> <mi> i </mi> </msub> </math>个,判断是否可以从这些数字中选出若干使它们的和恰好为k。 输入
输入包含多组数据。第一行为一个整数,代表数据组数,对于每组数据: 第一行输入n,k 第二行n个数,代表~. 第三行n个数,代表~.
输出每组数据输出一行 满足条件能使得和恰好为k,输出”yes”. 否则输出”no”.
样例输入
1 2 2 1 1 2 2
样例输出yes
这是动态规划的一种经典题型
这是matrix67大神的背包九讲的一种
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX 105
#define MAXN 100005
#define mem(x,v) memset(x,v,sizeof(x))
int a[MAX];
int m[MAX];
int dp[MAXN];
int main() {
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) scanf("%d", &m[i]);
mem(dp, -1);
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(j<a[i]||dp[j-a[i]]<=0) dp[j]=-1;
else{
dp[j]=max(dp[j],dp[j-a[i]]-1);
}//这是从一个博客看到的
}
}
if (dp[k] >= 0) printf("yes\n");
else printf("no\n");
}
return 0;
}
[Miracle_ma的专栏](http://blog.csdn.net/miracle_ma/article/details/51497619)
其中关键位置可以改为
for (int i = 1; i <= n; i++)
{
for (int j = 0; j <= k; j++)
{
if (dp[j] >= 0) dp[j] = m[i];
else if (j>=a[i] && dp[j - a[i]] > 0)
{
dp[j] = max(dp[j], dp[j - a[i]] - 1);
}
}
}