问题一描述:将一堆正整数划分为两组,要求两组的和相差最小并输出最小值。
Sample Input
5
1
2
3
4
5
Sample Output
1
idea:选择(1+3+5)-(2+4)=1
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
int main(){
int n,a[110],sum=0;
int dp[110000];//dp[]的范围!!!
memset(dp,0,sizeof(dp));
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
sum+=a[i];
}
//cout<<sum<<endl;
//sort(a,a+n);//简单排序然后选择行不通!典型的01背包问题
for(int i=0;i<n;i++)
for(int j=sum/2;j>=a[i];j--){
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
}
cout<<sum-2*dp[sum/2]<<endl;
}
/*
Sample Input
5
1
2
3
4
5
Sample Output
1*/
问题二描述:有n种不同大小的数字ai,每种各有mi个,判断从中选择出若干个使得他们的和为k.
输入1<=n<=100
1<=ai,mi<=100000;
1<=k<=100000
/*
input
3
3 5 8
3 2 2
17
output
yes
(暗示:3*3+8=17)数字 对应数字个数
*/
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<iostream>
bool dp[100][100];
using namespace std;
int main(){
int n,K;
int a[100],m[100];//dp[i][j]表示:前i种数字能否加成j(boolean类型) dp[n][K]确定yes与no
cin>>n;//输入数组的长度
for(int i=0;i<n;i++)
cin>>a[i];
for(int i=0;i<n;i++)
cin>>m[i];
cin>>K;
dp[0][0]=true;
for(int i=0;i<n;i++)
for(int j=0;j<=K;j++)
for(int k=0;k<=m[i]&&k*a[i]<=j;k++)//注意条件
dp[i+1][j]|=dp[i][j-k*a[i]];
if(dp[n][K])
cout<<"yes"<<endl;
else
cout<<"no"<<endl;
}