将元素平分成差值最小的两个集合(DP)
现有若干物品,要分成较为平均的两部分,分的规则是这样的:
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)的更多相关文章
- 【poj3522-苗条树】最大边与最小边差值最小的生成树,并查集
题意:求最大边与最小边差值最小的生成树.n<=100,m<=n*(n-1)/2,没有重边和自环. 题解: m^2的做法就不说了. 时间复杂度O(n*m)的做法: 按边排序,枚举当前最大的边 ...
- 用Scala实现集合中相邻元素间的差值
欢迎转载,转载请注明出处,徽沪一郎. 概要 代码这东西,不写肯定不行,新学Scala不久,将实际遇到的一些问题记录下来,日后也好查找. 今天讲的是如何计算同一集合中元素两两之间的差值,即求开始集合(a ...
- Poj 3522 最长边与最短边差值最小的生成树
题意: 让你求一颗生成树,使得最长边和最短边长度差值最小. 思路: 额!!!感觉这个思路会超时,但是ac了,暂时没什么别的好思路,那么就先说下这个思路,大牛要是有好的思路希望能在 ...
- LD1-K(求差值最小的生成树)
题目链接 /* *题目大意: *一个简单图,n个点,m条边; *要求一颗生成树,使得其最大边与最小边的差值是所有生成树中最小的,输出最小的那个差值; *算法分析: *枚举最小边,用kruskal求生成 ...
- 基于visual Studio2013解决面试题之1101差值最小
题目
- 【方法】list<?> 两个list集合 查找不同元素,求差值
//方法1 //自己声明list//思路,从list1中删除list2中相同的元素//使用循环遍历对比的方式删除//list1包含list2,list1多与list2//结束得出list1为不相同元素 ...
- 传说中的华为Python笔试题——两等长整数序列互换元素,序列和的差值最小(修正)
有两个序列a,b,大小都为n,序列元素的值任意整形数,无序:要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小. 1. 将两序列合并为一个序列,并排序,得到source ...
- find the most comfortable road(并差集,找差值最小的权值)
find the most comfortable road Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ...
- 218。重复元素II(重复元素的下标差值<=K)(哈希)
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k. 示例 1: 输入: nums ...
随机推荐
- idea 将java 项目 打包成jar包
记录一下,防止忘记.ps : 请忽略这个是web项目 1.idea 打包jar包 (1)首先打开Project Structure,选中Artifacts (2)点击绿色加号,选中jar ,然后选中f ...
- sping MVC 定时任务的设置
项目中用到了定时任务,写一篇随笔记录一下. 首先在Spring的配置文件ApplicationContext.xml文件的beans标签中添加 xmlns:task="http://www. ...
- 二十四、JavaScript之取字符串长度
一.代码如下 二.效果如下 <!DOCTYPE html> <html> <meta http-equiv="Content-Type" conten ...
- idea新建maven web项目
一.新建maven web项目 二.配置服务器 三.测试运行
- 我们是如何将 ToB 服务的交付能力优化 75%?
ToB 服务交付的方式分为公有云部署和私有化部署两种.其中,对成本敏感的中小企业往往采用公有云部署的方式,从而尽量减少成本.客单价较高的大型企业.政府.银行和事业单位,考虑到数据隐私.安全.合规等要求 ...
- cf 758D - Ability To Convert
从后往前贪心就好了.各种各样0的情况太BT了.. (各种爆long long,f**k) #include<bits/stdc++.h> #define LL long long #def ...
- x++ 与 ++x的区别
相信在很多编程语言中都会遇见这个问题,这对于刚入编程的人来说可能是相当懵逼了. 老师的官方说法是:操作符在前面先进行自身运算,再进行其他运算:操作符在后面,先进行其他运算再进行自身运算. 反正我这段话 ...
- (一)IOC基础推导及理论
环境准备:见java环境搭建,新建maven项目 1.写一个UserDao接口 public interface UserDao { public void getUser(); } 2.再写Dao的 ...
- MAT工具在MacBook的安装
当Java应用出现内存溢出的问题的时候,需要拿工具分析dump文件的.JDK自带的jvisualvm和jhat都可以使用,另外还有一个工具是 Memory Analyzer Tool ,支持独立运行和 ...
- 干货分享:Essay写作收集论据的三个方法
在很多时候,中国留学生写出的Essay在西方学术界看来是存在plagiarism的情况.并不是说咱们写的所有东西都是抄袭,而是思维逻辑和利用证据的方式与西方权威的academic writing不同. ...