Description
给定一个正整数的集合A={a1,a2,….,an},是否可以将其分割成两个子集合,使两个子集合的数加起来的和相等。例A = { 1, 3, 8, 4, 10} 可以分割:{1, 8, 4} 及 {3, 10}
Input
第一行集合元素个数n n <=300 第二行n个整数
Output
如果能划分成两个集合,输出任意一个子集,否则输出“no”
Sample Input
5 1 3 8 4 10
Sample Output
3 10
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define LL long long
const int N = 1e5 +10;
int n;
int a[400];
int vis[400];
int main()
{
ios::sync_with_stdio(false);
cin.tie();
memset(a,0,sizeof(a));
cin >> n;
int sum = 0;
int cnt = 0;
for(int i = 0; i < n ; i++)
{
cin>>a[i];
sum+=a[i];
if(a[i]==0) //之前代码 未考虑全部为0的情况会有错误 这里给特判掉了
cnt++;
}
if(cnt==n){
cout<<"0"<<endl;
return 0;
}
if(sum%2==1) //如果为奇数没办法实现划分
{
cout<< "no" <<endl;
return 0;
}
int **b;
b=(int **)malloc(sizeof(int *)*n); //动态分配
int t = floor(sum/2);
for(int i = 0; i < n ; i++)
{
b[i]=(int *)malloc(sizeof(int)*t);
}
//初始化
b[0][0]=1;
for(int j = 1 ; j <= t; j++)
{
b[0][j]=0;
}
b[0][a[0]]=1;
for(int i = 1; i < n; i++)
{
for(int j = 0; j<= t; j++)
{
if(b[i-1][j]==1||b[i-1][j-a[i]]==1)
{
b[i][j] = 1;
}
else
b[i][j] = 0;
}
}
//输出一组 可以做整数的拆分
if(b[n-1][t]==1)
{
int tmp = t;
int kk = 0;
for(int i = n-1 ; i >= 1; i--)
{
if(b[i][tmp]!=b[i-1][tmp])
{
if(kk==0)
cout<<a[i];
else
cout<<" "<<a[i];
tmp-=a[i];
kk = 1;
}
}
int flag =1;
for(int i = 0; i < n; i++)
{
if(tmp==a[i])
flag=0;
}
if(flag==0)
cout<<" "<<tmp<<endl;
}
else
{
cout<<"no"<<endl;
}
return 0;
}