概述
http://www.rqnoj.cn/Problem_72.html
题目:拔河比赛
问题编号:72
题目描述
superwyh的学校要举行拔河比赛,为了在赛前锻炼大家,老师决定把班里所有人分为两拨,进行拔河因为为锻炼所以为了避免其中一方的实力过强老师决定以体重来划分队伍,尽
量保持两个队伍的体重差最少,因为老师对结果没兴趣,所以只告诉老师最小的体重差是多少就行了。这个受苦受累的任务就交给superwyh了,因为这两天superwyh的后背间谍sjh
闹肚子了,所以只好superwyh亲自去调查每个人的体重,但是仅仅知道体重依然难以确定到底如何分配队伍,请各位oier帮助superwyh出出主意。
输入格式
第一行为人数(1<=n<=100),从第二行开始是每个人的体重(0<=m<=100)。
输出格式
最小体重差。
样例输入
10
23
41
12
样例输出
一、思路
刚开始,我一直想,如果,最后一个人不加,那子问题就成了求解前n-1个人 误差最接近第n个人的体重即可
10 30 60 70 即前3个人组成的两队后,最接近70即可
但是无法建立递推式,前2个人应该和 60 70 0 的子集差值最小的才对
那样就指数级别了
看了题解,将思路转换下,发现好简单
上个思路,有两个同时变化的相关量,即第一队和第二队的变化相互影响
转换为只求一队人的 01背包问题
即所有人的体重 sum / 2 只要让这个n个人里,尽可能的填满大小为sum/2的背包,那么
一队尽可能的由小变大接近均值,那么另外一对肯定是由大到小接近均值,直到这一队无法变大
那么 这时,两者已经尽可能接近了
sum - f[n][sum/2] * 2就是最小差值
二、算法
f[101][5001]来描述,给定i个人,j大小背包时,所能装下的最大重量
height[101] 来保存每个人的重量
f[i][j] = max(f[i-1][j], f[i-1][j-height[i]]);装第i个人或者不装,就只有这两种可能
1、读入n
2、读入每个人的重量,并求出总和sum
3、初始条件:全为0
3、动态规划,二重循环
第一重:i个人
第二重:j大小的背包
f[i][j] = max(f[i-1][j], f[i-1][j-height[i]])
4、输出结果
sum - f[n][arverage]*2 两者的差值
终于AC
代码如下:
#include <iostream.h>
#include <fstream.h>
int main()
{
int n, height[101], sum, average, min, i, j;
static int f[101][5001] = {0};
//ifstream inFile("e:\test.txt");
//读入人数n
cin>>n;
//inFile>>n;
//读入每个人体重
sum = 0;
for (i=1; i<=n; i++)
{
cin>>height[i];
//inFile>>height[i];
sum += height[i];
}
average = sum / 2;
//动态规划
for (i=1; i<=n; i++)
{
for (j=1; j<=average; j++)
{
f[i][j] = f[i-1][j];
if (j>=height[i] && f[i][j] < f[i-1][j-height[i]]+height[i])
{
f[i][j] = f[i-1][j-height[i]] + height[i];
}
}
}
//输出结果
cout<< sum - f[n][average]*2;
//inFile.close();
return 0;
}
最后
以上就是发嗲眼睛为你收集整理的拔河比赛-动态规划 题目描述 输入格式 输出格式 样例输入 样例输出的全部内容,希望文章能够帮你解决拔河比赛-动态规划 题目描述 输入格式 输出格式 样例输入 样例输出所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复