现有若干物品,要分成较为平均的两部分,分的规则是这样的:

1)两部分物品的个数最多只能差一个。

2)每部分物品的权值总和必须要尽可能接近。

现在请你编写一个程序,给定现在有的物品的个数以及每个物品的权值,求出按上述规则分成两部分后每部分的权值总和。

输入格式

第一行为一个整数n(1≤n≤200),表示现在有的物品的个数。

以下的n行每行一个整数,表示每个物品的权值(1≤ai≤40)。

输出格式

只有一行,包含两个数,即分成的每部分的权值总和,较小的一个值放在前面,两个数用空格隔开。

样例输入


样例输出

 

对于本题,因为需要再计算过程中保证你计算的结果是n\2 或 n\2+1个物品。所以这个时候我们就必须要使用二维数组,来记录你使用物品个数。

最后我们在找出n\2 或 n\2+1(n是奇数)个物品中权值最大的就行了。

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <ctime>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const LL MOD=1e9+;
const double PI = acos(-);
const double eps =1e-;
#define Bug cout<<"---------------------"<<endl
const int maxn=1e5+;
using namespace std; int a[];
int dp[][*];//dp[i][j]表示当前有i个物品总权值为j int main()
{
#ifdef DEBUG
freopen("sample.txt","r",stdin);
#endif
// ios_base::sync_with_stdio(false);
// cin.tie(NULL); int n;
scanf("%d",&n);
int sum=;
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
dp[][]=;
for(int i=;i<=n;i++)
{
for(int j=n/+;j>=;j--)
{
for(int k=sum/;k>=;k--)
{
if(dp[j][k]) dp[j+][k+a[i]]=;
}
}
}
for(int i=sum/;i>=;i--)
{
if(dp[n/][i]||(dp[n/+][i]&&n&))
{
printf("%d %d\n",i,sum-i);
break;
}
} return ;
}

现有N个物品,每块物品有一个权值, 现在想将这N个物品分成权值相同的两部分,可以从这N个物品中任取M(1≤M≤N)个来构建。但是不知道这些物品能否使分成的两部分具有同样的权值,也不

知道如果能分成权值相同的两部分,每部分的最大权值是多少。

给定物品的数量N(1≤N≤100)和每个物品的权值wi ( N个物品的权值总和不超过2000 )。

你的任务是判断能否在这些物品中挑一部分,把他们分成权值相同的两部分,如果能,则输出所能分成两部分的最大权值和,否则输出" Impossible"。

输入格式

输入的第一行为一个数 N,表示物品的数量。

第二行为 N 个数,第 i 个数表示第 i 个物品的权值。

输出格式

输出仅包含一行,如果能分成权值相同的两部分,则输出每部分的最大权值和,否则输出一个字符串"Impossible"。

样例输入

    

样例输出


本题用dp[i][j]表示已处理i件物品,而分成的两部分权值差为j的一种状态。

所以我们对这两部分我们有三种操作

1)把第i个物品放入总权值大的一部分中,大的变得更大

2)把第i个物品放入总权值小的一部分中,然后就会发生两种情况

(1)小的变成大的

(2)小的还是小的

所以我们有三种状态转移方程。对应的代入如上。

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <ctime>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const double PI = acos(-);
const double eps =1e-;
#define Bug cout<<"---------------------"<<endl
const int maxn=1e5+;
using namespace std; int a[];
int dp[][]; int main()
{
#ifdef DEBUG
freopen("sample.txt","r",stdin);
#endif
// ios_base::sync_with_stdio(false);
// cin.tie(NULL); int n;
scanf("%d",&n);
int sum=;
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,-,sizeof(dp));
dp[][]=;
for(int i=;i<=n;i++)
{
sum+=a[i];
for(int j=;j<=sum;j++)
{
if(dp[i-][j] > dp[i][j])//不选(初始化)
dp[i][j] = dp[i-][j];
if(j >= a[i] && dp[i-][j-a[i]] >= )//大 -> 大
dp[i][j] = max(dp[i][j],dp[i-][j-a[i]]);
if(dp[i-][j+a[i]] >= )//小 -> 小
dp[i][j] = max(dp[i][j],dp[i-][j+a[i]]+a[i]);
if(a[i] >= j && dp[i-][a[i]-j] >= )// 小 -> 大
dp[i][j] = max(dp[i][j],dp[i-][a[i]-j]+a[i]-j);
}
}
if(dp[n][]) printf("%d\n",dp[n][]);
else printf("Impossible\n"); return ;
}

-

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

  1. 【poj3522-苗条树】最大边与最小边差值最小的生成树,并查集

    题意:求最大边与最小边差值最小的生成树.n<=100,m<=n*(n-1)/2,没有重边和自环. 题解: m^2的做法就不说了. 时间复杂度O(n*m)的做法: 按边排序,枚举当前最大的边 ...

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

    欢迎转载,转载请注明出处,徽沪一郎. 概要 代码这东西,不写肯定不行,新学Scala不久,将实际遇到的一些问题记录下来,日后也好查找. 今天讲的是如何计算同一集合中元素两两之间的差值,即求开始集合(a ...

  3. Poj 3522 最长边与最短边差值最小的生成树

    题意:       让你求一颗生成树,使得最长边和最短边长度差值最小. 思路:      额!!!感觉这个思路会超时,但是ac了,暂时没什么别的好思路,那么就先说下这个思路,大牛要是有好的思路希望能在 ...

  4. LD1-K(求差值最小的生成树)

    题目链接 /* *题目大意: *一个简单图,n个点,m条边; *要求一颗生成树,使得其最大边与最小边的差值是所有生成树中最小的,输出最小的那个差值; *算法分析: *枚举最小边,用kruskal求生成 ...

  5. 基于visual Studio2013解决面试题之1101差值最小

     题目

  6. 【方法】list<?> 两个list集合 查找不同元素,求差值

    //方法1 //自己声明list//思路,从list1中删除list2中相同的元素//使用循环遍历对比的方式删除//list1包含list2,list1多与list2//结束得出list1为不相同元素 ...

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

    有两个序列a,b,大小都为n,序列元素的值任意整形数,无序:要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小. 1. 将两序列合并为一个序列,并排序,得到source ...

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

    find the most comfortable road Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  9. 218。重复元素II(重复元素的下标差值<=K)(哈希)

    给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k. 示例 1: 输入: nums ...

随机推荐

  1. objectarx 批量倒角

    这个插件支持AcDbPolyline的倒角,封闭的和没封闭的都可以.刚开始做的时候,发现倒一个角借助云幽课堂里的代码就可以做,后来做一条从左开始画的非封闭的多段线,发现向上凹和向下凹的角不能同时被倒, ...

  2. 《新标准C++程序设计》3.3-3.4(C++学习笔记7)

    1.构造函数.析构函数和变量的生存期 构造函数在对象生成时会被调用,析构函数在对象消亡时会被调用. 程序示例分析: (1) #include<iostream> using namespa ...

  3. Delphi MD5

    unit uMD5; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics; type MD5Count = ...

  4. Scanner类的next()方法和nextLine()方法的区别(简)

    1.  空白符:回车.空格.tab等 2.  next()方法读取到空白符就结束 3. nextLine()方法读取到回车结束,也就是 "\r"

  5. 解决Spring Mvc中接受参数绑定重名的方法

    html页面 <form method='post' action='url'> 用户名 <input type='text' name='name'> 用户id <in ...

  6. gdb 常用选项

    gdb 常用选项 help:查看命令帮助,具体命令查询在gdb中输入help + 命令,简写h run:重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件),简写r st ...

  7. POJ 1426:Find The Multiple

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000KB   64bit IO Format: %I64d & %I64u Su ...

  8. iOS 保存图片(视频)到相册

    1.C语言函数方式实现 注意:UIImageWriteToSavedPhotosAlbum方法必须实现代理方法,否则会崩溃. //参数1:图片对象 //参数2:成功方法绑定的target //参数3: ...

  9. 如何通过C语言获取主机WLAN下的IPv4地址,MAC地址

    #include "stdio.h" #include "windows.h" void GetHostWLAN_IPv4_AND_MAC(char IPv4[ ...

  10. hive的join优化

    “国际大学生节”又称“世界大学生节”.“世界学生日”.“国际学生日”.1946年,世界各国学生代表于布拉格召开全世界学生大会,宣布把每年的11月17日定为“世界大学生节”,以加强全世界大学生的团结和友 ...