01背包;感谢ZCK大佬

题目描述

学校举行拔河比赛,所有的人被分成了两组,每个人必须(且只能够)在其中的一组,要求两个组的人数相差不能超过1,且两个组内的所有人体重加起来尽可能地接近。

输入

输入中的第一行只有一个整数n(1≤n≤100),第二行有n个以空格分隔的整数,表示每人的体重wi(所有的wi均满足:1≤wi≤450)。

输出

输出只有一行,该行有两个整数,以一个空格分隔。第一个数表示体重较大的组的体重总和,第二个数表示体重较小的组的体重总和。

题面看上去很短,题意也很好理解:就是将n个人分成两组,在人数差不大于1的情况下使它们差最小。

用cnt表示它们的体重之和,则是使两组重量之和尽可能接近cnt / 2。那么就是在cnt / 2的空间里尽可能地使选入的人重。乍一看跟“挤牛奶”没区别,都是两维的dp其中增加一位限制人数。i,j,k三维循环,

for (int i=; i<=n; i++)
for (int j=i; j>=; j--)
for (int k=cnt; k>=a[i]; k--)
因为每个人只能选一次,所以j,k逆序

i,j,k循环


先来讲讲我最早的想法:

这是一份80,一份90的代码

初始化是f[][] = 0

在这种dp[][]方程的定义下,f[i][j]表示1..i人,凑成0..j范围内能凑成的最大重量(我知道这非常奇怪。事实上,在请教ZCK之前我甚至以为这个f[i][j]表示i个人能否凑出j。所以我发现"当f[i][j] != 0时,f[i][j] != j "这个现象时候才开始怀疑我的dp方程)

f[j][k] = max(f[j][k], f[j-1][k-a[i]]+a[i]);

在最终选取ans的时候,由于我们希望ans最接近cnt / 2,那么循环是“cnt / 2 ... 1“的,则ans = max{f[n / 2][]}。在这种情况下,不能够只判断 f[n / 2][i] 。虽然这看上去很有道理——如果n是奇数,用cnt - f[n / 2][i]就是奇数那一队的人数嘛!ZCK解释说:“f[n / 2][] 和 f[n / 2+1][] (n为奇数)是两条不同的数轴,不能保证f[n / 2][]上最接近cnt / 2的值比f[n / 2+1][]上的更优。”由于我们枚举的f[n / 2][] ≤ cnt / 2,那么对应的f[n / 2+1][]就是 ≥ cnt / 2的。有可能n / 2+1人能凑出更接近cnt / 2的!

可能会想到:既然dp时候已经把f[][cnt ... 1]都表示出来了,那么只需要在寻找ans的时候改动一下,变成这样

for (int j=cnt; j>=1; j--)
{
if (abs(cnt - 2*f[n/2][j]) < abs(cnt-2*ans))ans = f[n/2][j]
}

实际上,这样的判断只有70分。

并不是因为寻找ans的过程有问题,是因为f[][]所表示的东西不是我们想要的


这原因是初始化。

memset(f,-127,sizeof(f));  将f初始化为一个很小很小的数,这样f[i][j]表示的东西就不一样了
f[0][0]=0;  必要的

这样改了之后,只需要"cnt ... 1"判f[n / 2][]即可.

当然"cnt / 2 ... 1"判f[n / 2][], f[n / 2+1][]也可

因为我的dp方程太凌乱了……为了阿掉这题爆交共30+……


ZCK:你的dp方程到底想表示什么???直接bool不就好了吗

bool f[103][45035];

实际上,这的确是最简洁而且dp方程表示最明确的一种方法……


讲了这么多,实际上只是想说明dp方程的 定义 和 初始化 对于dp来说有多么重要。短短的一句初始语句或者在脑海中闪过一瞬的dp方程碎片,就足以上演化爆零为AC的奇迹。一个max和一个if看上去没多大差别,事实上后续的处理可能失之千里。考虑问题要仔细全面,这绝对不是一句空话。

【dp】拔河比赛的更多相关文章

  1. codevs 1959 拔河比赛--判断背包内刚好装满n/2个物品

    1959 拔河比赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 一个学校举行拔河比赛,所有的 ...

  2. codevs1959拔河比赛(二维费用背包)

    1959 拔河比赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 一个学校举行拔河比赛,所有的人被分成了两组,每个人 ...

  3. CODEVS 1959 拔河比赛(另一版本)

    题目描述 Description 一个学校举行拔河比赛,所有的人被分成了两组,每个人必须(且只能够)在其中的一组,要求两个组的人数相差不能超过1,且两个组内的所有人体重加起来尽可能地接近. 输入描述 ...

  4. rqnoj71 拔河比赛

    题目描述 superwyh的学校要举行拔河比赛,为了在赛前锻炼大家,老师决定把班里所有人分为两拨,进行拔河因为为锻炼所以为了避免其中一方的实力过强老师决定以体重来划分队伍,尽 量保持两个队伍的体重差最 ...

  5. c 指针 及其位运算循环移动拔河比赛问题代码

    week_2_day1_7.7 周一//用字符数组 来实现 字母大小写转换#include<stdio.h>void desc( char *a ,int n){    char  *i ...

  6. [深搜]A. 【例题1】拔河比赛

    A . [ 例 题 1 ] 拔 河 比 赛 A. [例题1]拔河比赛 A.[例题1]拔河比赛 解析 模板题,选与不选 Code #include <bits/stdc++.h> #defi ...

  7. 【C/C++】拔河比赛/分组/招商银行

    题目:小Z组织训练营同学进行一次拔河比赛,要从n(2≤n≤60,000)个同学中选出两组同学参加(两组人数可能不同).对每组同学而言,如果人数超过1人,那么要求该组内的任意两个同学的体重之差的绝对值不 ...

  8. 【codevs1959】拔河比赛

    题目大意:给定一个有 N 个数的集合,将这 N 个数均分成两堆,求差值最小是多少. 题解:有关集合选数的问题,应该是背包问题,同时要求均分可知,选出的物品数目也应该是背包费用的一个维度,因此这是一个多 ...

  9. 【解题报告】[动态规划]RQNOJ - PID72 / 拔河比赛

    原题地址:http://www.rqnoj.cn/problem/72 解题思路:基本的01背包问题. 要求的就是在这些人中选出一些人,使得这些人的体重的和 不超过所有人的体重的一半 并最大. 代码: ...

随机推荐

  1. 题解 P1162 【填涂颜色】

    看到题目规模是n(1≤n≤30)即最大规模为30*30 本蒟蒻有个奇妙的想法!! 核心思路:搜索地图内除开被1包围着的0,并标注为1(即不填色) !!!那么,我们可以从每一个边界点开始去搜索 话不多说 ...

  2. 5本自然语言处理书单-附pdf

    文章发布于公号[数智物语] (ID:decision_engine),关注公号不错过每一篇干货. 自然语言处理(英语:Natural Language Processing,缩写作 NLP)是人工智能 ...

  3. 快速对接payjs的个人支付接口(收银台模式)

    近期在了解个人支付接口,希望能解决我在微信上支付的问题.找了很多平台对比再三,感觉payjs比较专业,其它多是模仿payjs的东西.同时支持支付宝和微信,由于本人支付宝还没开通(需要有一定流量才给开通 ...

  4. [题解](折半搜索/高斯消元枚举自由元)BZOJ_1770_Lights

    状压,时间空间都不行,如果每次搜索一半就可以省下很多空间,用map记下每种状态的答案,最后再把两次的答案合并 然而正解是高斯消元解异或方程组,最后搜索自由元 #include<iostream& ...

  5. 基于华为云语音通知 VoiceCall 的应用上线记录并分享.NET CORE DEMO

    最近公司要上线语音通知功能,需求如下: 场景:发生报警时,自动通知到指定的手机号,同时,提供几个按键选项,例如,语音通知如下: “您好,XXX小区发生XXXX报警,按1确认报警,按2忽略报警,按3屏蔽 ...

  6. JavaScript Allongé 序幕:值和表达式

    序幕:值和表达式   下面的内容非常基础,然而,就像大多数的故事一样,在最初的时候开始才是最好的开端. 想象一下,我们要去最喜欢的咖啡馆,他们会为你制作几乎任何你想要的饮料,从小而强烈的 Espres ...

  7. TDH-search常用命令

    一.指令部分:1.search管理界面地址: http://172.20.230.110:9200/_plugin/head/ 2.集群状态查看命令: curl -XGET 'localhost:92 ...

  8. Unity AssetBundle笔记

    1.入门: Resources:表示U3D自动将资源打成一个AssetBundle包,所有放在Resources下的文件夹都会打成一个AssetBundle包,资源非常大,Resources文件夹在真 ...

  9. 前端之CSS布局模型

    一.css布局模型: 流动模型(Flow) 浮动模型(Float) 层模型(Layer) 1.流动模型: 页面在没有设置任何css样式,元素按照本身的特性在浏览器中显示,这样的布局模型称为流动模型: ...

  10. JAVA 时间的使用

    今天老师又没有讲新课,不过讲了练习题,扩展了一下我们的思维. 今天就讲一下如何获取时间吧. 代码: import java.util.* public class Test{ public stati ...