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

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. 基于云开发开发 Web 应用(三):云开发相关数据调用

    介绍 在完成了 UI 界面的实现后,接下来可以开始进行和云开发相关的数据对接.完成数据对接后,应用基础就打好了,接下来的就是发布上线以及一些小的 feature 的加入. 配置 在进行相关的配置调用的 ...

  2. 73.Python中ORM聚合函数详解:Count

    Count:用来求某个数据的个数. 在以下所有的示例中所采用的模型为: from django.db import models # 定义作者模型 class Author(models.Model) ...

  3. C++ for无限循环~

    无限循环 如果条件永远不为假,则循环将变成无限循环.for 循环在传统意义上可用于实现无限循环.由于构成循环的三个表达式中任何一个都不是必需的,您可以将某些条件表达式留空来构成一个无限循环. #inc ...

  4. Apache部署Django+Vue

    首先部署Vue,后端项目django开5000端口,所以vue里的路由是ip:5000,然后打包npm run build 生成dist文件 把dist文件里的index.html和static放在/ ...

  5. 【golang】golang文本处理

    golang文本字符串操作:包含 合并 连接 分割 取索引 前缀后缀检测 消除字符串 消除空格 golang字符串操作需要用到 strings这个包 str := "hello world& ...

  6. 阿里巴巴技术总监全解中台架构19页ppt

    //初创时,快速上线 单体架构至少撑了3年 //分布式,中间件基座 //平台化,内部是简单服务,对于业务侧就是快速上线 //平台化之后由于多平台协作问题,再次出现问题: 效率仍然不能匹配业务发展之需要 ...

  7. 四、CI框架之通过URL路径访问C中的函数

    一.在C中写一个test001函数 二.在路径http://127.0.0.1/CodeIgniter-3.1.10/index.php/welcome/test001中访问 不忘初心,如果您认为这篇 ...

  8. Maven - Repository(存储库)

    版权所有,未经授权,禁止转载 章节 Maven – 简介 Maven – 工作原理 Maven – Repository(存储库) Maven – pom.xml 文件 Maven – 依赖管理 Ma ...

  9. redis(六)---- 简单延迟队列

    延迟队列的应用场景也很常见,例如:session的超时过期.自动取消未付款订单等等.redis中有一种数据结构叫做zset,即有序集合.元素类型为String类型,且元素具有唯一性不能重复,每个元素可 ...

  10. POJ 1995:Raising Modulo Numbers 快速幂

    Raising Modulo Numbers Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5532   Accepted: ...