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:arr){
 6             sum += i;
 7         }
 8         boolean[][] flag = new boolean[n/2+1][sum/2+1];
 9         for(int i=0;i<n/2+1;i++){
10             for(int j=0;j<sum/2+1;j++){
11                 flag[i][j] = false;
12             }
13         }
14         flag[0][0] = true;
15         for(int k = 0;k<n;k++){
16             for(int i=k>n/2?n/2:k;i>=1;i--){
17                 //遍历s(k,i)
18                 for(int j=0;j<=sum/2;j++){
19                     if(j>=arr[k]&&flag[i-1][j-arr[k]]){
20                         flag[i][j] = true;
21                     }
22                 }
23             }
24         }
25         for(int i = sum/2;i>=0;i++){
26             if(flag[n/2][i]) {
27                 System.out.println(i);
28                 break;
29             }
30         }
31     }

我觉得比较难理解的地方就是flag[i-1]这一行是什么意思:代表从k中取i-1个数,他们的各种和的可能的体现(存在即为true)

最里面一层循环的意思是:从i-1这一行中取各种和 然后加上arr[k]凑成i个数的和,体现在flag[i]里面。

第二层循环的意思是:执行1-i这么多行

最外面一层就是不断往里面加数。

我测试的例子不多,可能有遗漏的地方,请留言指出来,难以理解的地方也可以留言讨论。

原文地址:https://www.cnblogs.com/kevin-lee123/p/11563466.html

时间: 2024-10-01 02:22:46

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

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

题目描述: 有两个数组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

欧拉函数 求小于某个数并与其互质的数的个数

1 const int maxn=32790; 2 int euler[maxn+2]; 3 void make() 4 { 5 euler[1]=0; 6 for(int i=2;i<=maxn;++i) 7 euler[i]=i; 8 for(int i=2;i<=maxn;++i) 9 if(euler[i]==i) 10 for(int j=i;j<=maxn;j+=i) 11 euler[j]=euler[j]/i*(i-1); 12 } euler[n]代表的就是在n之前与n

传说中的华为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

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

现有若干物品,要分成较为平均的两部分,分的规则是这样的: 1)两部分物品的个数最多只能差一个. 2)每部分物品的权值总和必须要尽可能接近. 现在请你编写一个程序,给定现在有的物品的个数以及每个物品的权值,求出按上述规则分成两部分后每部分的权值总和. 输入格式 第一行为一个整数n(1≤n≤200),表示现在有的物品的个数. 以下的n行每行一个整数,表示每个物品的权值(1≤ai≤40). 输出格式 只有一行,包含两个数,即分成的每部分的权值总和,较小的一个值放在前面,两个数用空格隔开. 样例输入 3

【方法】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; } } } //

01: 与指定数字相同的数的个数(1.6)

描述 输出一个整数序列中与指定数字相同的数的个数. 输入输入包含三行: 第一行为N,表示整数序列的长度(N <= 100): 第二行为N个整数,整数之间以一个空格分开: 第三行包含一个整数,为指定的数字m.输出输出为N个数中与m相同的数的个数.样例输入 3 2 3 2 2 样例输出 2 #include<cstdio> int main(){ int n,m; int a[110]; scanf("%d",&n); for (int i=1;i<=n;i

与指定数字相同的数的个数

总时间限制:  1000ms 内存限制:  65536kB 描述 输出一个整数序列中与指定数字相同的数的个数. 输入 输入包含三行:第一行为N,表示整数序列的长度(N <= 100):第二行为N个整数,整数之间以一个空格分开:第三行包含一个整数,为指定的整数m. 输出 输出为N个数中与m相同的数的个数. 样例输入 3 2 3 2 2 样例输出 2 #include<stdio.h> int main() { int n,a[101],b,ans; scanf("%d"

01:与指定数字相同的数的个数

总时间限制:  1000ms 内存限制:  65536kB 描述 输出一个整数序列中与指定数字相同的数的个数. 输入 输入包含三行:第一行为N,表示整数序列的长度(N <= 100):第二行为N个整数,整数之间以一个空格分开:第三行包含一个整数,为指定的整数m. 输出 输出为N个数中与m相同的数的个数. 样例输入 3 2 3 2 2 样例输出 2 #include<stdio.h> int main() { int a=0,b=0,c=0; int shu[100]={0}; scanf

1-6-01:与指定数字相同的数的个数

描述 输出一个整数序列中与指定数字相同的数的个数. 输入 输入包含三行:第一行为N,表示整数序列的长度(N <= 100):第二行为N个整数,整数之间以一个空格分开:第三行包含一个整数,为指定的整数m. 输出 输出为N个数中与m相同的数的个数. 样例输入 3 2 3 2 2 样例输出 2 #include<stdio.h>int main(){    int N,temp[10001]={0},m,s=0,i;    scanf("%d",&N);    fo