将元素平分成差值最小的两个集合(DP)
Posted JmFv5
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将元素平分成差值最小的两个集合(DP)相关的知识,希望对你有一定的参考价值。
现有若干物品,要分成较为平均的两部分,分的规则是这样的:
1)两部分物品的个数最多只能差一个。
2)每部分物品的权值总和必须要尽可能接近。
现在请你编写一个程序,给定现在有的物品的个数以及每个物品的权值,求出按上述规则分成两部分后每部分的权值总和。
输入格式
第一行为一个整数n(1≤n≤200),表示现在有的物品的个数。
以下的n行每行一个整数,表示每个物品的权值(1≤ai≤40)。
输出格式
只有一行,包含两个数,即分成的每部分的权值总和,较小的一个值放在前面,两个数用空格隔开。
样例输入
3 35 20 32
样例输出
35 52
对于本题,因为需要再计算过程中保证你计算的结果是n\2 或 n\2+1个物品。所以这个时候我们就必须要使用二维数组,来记录你使用物品个数。
最后我们在找出n\2 或 n\2+1(n是奇数)个物品中权值最大的就行了。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 #include <ctime> 14 const int INF=0x3f3f3f3f; 15 typedef long long LL; 16 const int mod=1e9+9; 17 const LL MOD=1e9+7; 18 const double PI = acos(-1); 19 const double eps =1e-8; 20 #define Bug cout<<"---------------------"<<endl 21 const int maxn=1e5+10; 22 using namespace std; 23 24 int a[205]; 25 int dp[205][205*20];//dp[i][j]表示当前有i个物品总权值为j 26 27 int main() 28 { 29 #ifdef DEBUG 30 freopen("sample.txt","r",stdin); 31 #endif 32 // ios_base::sync_with_stdio(false); 33 // cin.tie(NULL); 34 35 int n; 36 scanf("%d",&n); 37 int sum=0; 38 for(int i=1;i<=n;i++) 39 { 40 scanf("%d",&a[i]); 41 sum+=a[i]; 42 } 43 dp[0][0]=1; 44 for(int i=1;i<=n;i++) 45 { 46 for(int j=n/2+1;j>=0;j--) 47 { 48 for(int k=sum/2;k>=0;k--) 49 { 50 if(dp[j][k]) dp[j+1][k+a[i]]=1; 51 } 52 } 53 } 54 for(int i=sum/2;i>=0;i--) 55 { 56 if(dp[n/2][i]||(dp[n/2+1][i]&&n&1)) 57 { 58 printf("%d %d\n",i,sum-i); 59 break; 60 } 61 } 62 63 return 0; 64 }
-
以上是关于将元素平分成差值最小的两个集合(DP)的主要内容,如果未能解决你的问题,请参考以下文章