标签:枚举 个数 思路 sum += 问题 its ace cout
给定一个正整数的集合A={a1,a2,….,an},是否可以将其分割成两个子集合,使两个子集合的数加起来的和相等。例A = { 1, 3, 8, 4, 10} 可以分割:{1, 8, 4} 及 {3, 10}
第一行集合元素个数n n <=300 第二行n个整数
如果能划分成两个集合,输出任意一个子集,否则输出“no”
5
1 3 8 4 10
3 10
dp[i][j] = if(dp[i-1][j] || dp[i-1][j-v[i]]) // j>=v[i]
if(j >= a[i] && dp[i][j] && !dp[i-1][j]) printf("%d ", a[i]);
#include<bits/stdc++.h>
using namespace std;
int a[305];
int main () {
int n, sum = 0;
cin >> n;
for(int i = 1; i <= n; ++i) {
scanf("%d", a+i);
sum += a[i];
}
if(sum%2) { // 和为奇数直接输出no
cout << "no";
return 0;
}
sum/=2;
int dp[n+5][sum+5];
memset(dp, 0, sizeof dp);
dp[1][0] = 1; // 这里不能少
dp[1][a[1]] = 1; // 同上
for (int i = 2; i <= n; ++i) { // 枚举物品
for (int j = 0; j <= sum; ++j) { // 枚举容量
if(dp[i-1][j]) {
dp[i][j] = 1;
}
if(j >= a[i] && dp[i-1][j-a[i]]) {
dp[i][j] = 1;
//cout << "debug:" << i << " " << j;
}
}
}
if(!dp[n][sum]) { // 没有找到可行方案
printf("no");
return 0;
}
// 路径输出,倒序
for (int i = n, j = sum; i >= 1&&j>0; --i) {
if(j >= a[i] && dp[i][j] && !dp[i-1][j]) {
printf("%d ", a[i]);
j -= a[i];
}
}
return 0;
}
标签:枚举 个数 思路 sum += 问题 its ace cout
原文地址:https://www.cnblogs.com/knightoflake/p/14686898.html