将元素平分成差值最小的两个集合(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 }

-

原文地址:https://www.cnblogs.com/jiamian/p/12219569.html

时间: 2024-10-01 03:54:45

将元素平分成差值最小的两个集合(DP)的相关文章

n个数分为两组,两组数的个数尽可能相等,差值最小

题目描述:对于有n个数的数组,分为两组,这两组的数的个数尽可能相等(不超过1),同时两组的数之和的差值最小. 这个题目使用类似0-1背包问题,思路:从k个数中选i个数,求所有可能的和,并把这些和放在flag中用true表示.(k,i,flag见代码) 1 public static void main(String[] args){ 2 int[] arr = {1 , 2 , 3 , 5 , 7 , 8 , 9}; 3 int n = 7; 4 int sum = 0; 5 for(int i

hdu1598find the most comfortable road(并查集+枚举,求起点到终点的边中最大边减最小边差值最小)

Problem Description XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Flycar限制了固定的Speed,同时XX星人对 Flycar的"舒适度"有特殊要求,即乘坐过程中最高速度与最低速度的差越小乘坐越舒服 ,(理解为SARS的限速要求,flycar必须瞬间提速/降速,痛苦呀 ), 但XX星人对时间却没那么多要求.要你找出一条城市间的最舒适的路径.(

用Scala实现集合中相邻元素间的差值

欢迎转载,转载请注明出处,徽沪一郎. 概要 代码这东西,不写肯定不行,新学Scala不久,将实际遇到的一些问题记录下来,日后也好查找. 今天讲的是如何计算同一集合中元素两两之间的差值,即求开始集合(a,b,c,d)中(b-a,c-b,d-c) 解法 val l1 = 1 to 10 toList val l2 = l1.tail l1.zip(l2).map(p=>(p._2 - p._1) 上述代码即可求出两两差值.代码含义稍作解释: tail表示一个集合中除首元素外的剩余元素,也是一个集合.

交换两个数组的元素使之总和的差值最小

题目描述: 有两个数组a,b,大小都为n,数组元素的值任意整型数,无序: 要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小. #include "stdafx.h" #include <math.h> #include <time.h> #include <stdlib.h> void print_arr(int a[], int b[], int n) { printf("a: "); for (int

【方法】list&lt;?&gt; 两个list集合 查找不同元素,求差值

//方法1 //自己声明list for(int i=0;i<list1.size();i++) { for(int j=0;j<list2.size();j++) { if (list1.get(i).toString().equals(list2.get(j).toString()))//查找相同的元素 { list1.remove(i);//删除list1下标为i的元素 i--; //删除下标后list元素变少需要减少下标值,list不会和数组一样占用空间 break; } } } //

传说中的华为Python笔试题——两等长整数序列互换元素,序列和的差值最小(修正)

有两个序列a,b,大小都为n,序列元素的值任意整形数,无序:要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小. 1. 将两序列合并为一个序列,并排序,得到sourceList2. 拿出最大元素Big,次大的元素Small3. 在余下的序列S[:-2]进行平分,得到序列max,min4. 将Small加到max序列,将Big加大min序列,重新计算新序列和,和大的为max,小的为min. 如下,提供递归版本和迭代版本的解体思路: #!/usr/bin/env py

find the most comfortable road(并差集,找差值最小的权值)

find the most comfortable road Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5359    Accepted Submission(s): 2327 Problem Description XX 星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超

华为上机题之输出身高差值最小的俩个人

要从5个人中选取2个人作为礼仪,其中每个人的身高范围为160-190,要求2个人的身高差值最小(如果差值相同的话,选取其中最高的两人),以升序输出两个人的身高. Smple     input:161 189 167 172 188 Sample outPut: 188 189 分析: 看到这个题,最小想到的全排问题,从5个人中抽2个人出来,一共有10中情况.计算出来后,马上想到的是用排序来这10种情况的差值,选取差值最小那一组的俩个人. 接下来想到的是用什么数据结构.每一种情况需要存储a.b两

整数数组中两两之差绝对值最小的值

题目1: 有一个整数数组,请求出两两之差绝对值最小的值,记住,只要得出最小值即可,不需要求出是哪两个数. 题目2:请求出最小连续子序列绝对值和,也就是求连续子序列之和的绝对值最小值 针对问题1: 方法<1>:暴力的方式.遍历所有的两个数的差,记录最小值.算法的复杂度O(n2) 方法<2>:两个数要想差的绝对值最小,肯定是需要两个数大小相近.故有思路:先对数组进行排序,然后遍历一遍,相邻的数相减,记录绝对值最小的数. 方法<3>:将现在的问题进行转化: 设这个整数数组是a