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. E - Multiplication Puzzle

    #include <iostream> #include <algorithm> #include <cstring> #include <cstdio> ...

  2. PostgreSQL-3-DDL数据定义语言

    1.创建/删除新的数据库 \l  查看现有数据库 \h CREATE DATABASE  查看CREATE DATABASE语句说明 \h DROP DATABASE 查看DROP DATABASE语 ...

  3. python操作json来存储简单的数据,pickle来操作复杂的数据

    json作为不同语言间进行数据交互的媒介,在当下已经渐渐取代了之前的xml,看一波python操作json # coding = ascii import json import pickle imp ...

  4. Zynq7000开发系列-6(QT开发环境搭建:Ubuntu、Zynq)

    操作系统:Ubuntu14.04.5 LTS 64bit Qt:Qt 5.4.2 (qt-opensource-linux-x64-5.4.2.run.qt-everywhere-opensource ...

  5. HDU6440(费马小定理)

    其实我读题都懵逼--他给出一个素数p,让你设计一种加和乘的运算使得\[(m+n)^p = m^p+n^p\] 答案是设计成%p意义下的加法和乘法,这样:\[(m+n)^p\ \%\ p = m+n\] ...

  6. 551 Student Attendance Record I 学生出勤纪录 I

    给定一个字符串来代表一个学生的出勤纪录,这个纪录仅包含以下三个字符:    'A' : Absent,缺勤    'L' : Late,迟到    'P' : Present,到场如果一个学生的出勤纪 ...

  7. Azkaban的架构(三)

    Azkaban是什么?(一) Azkaban的功能特点(二) 不多说,直接上干货! http://www.cnblogs.com/zlslch/category/938837.html Azkaban ...

  8. C#入门笔记3 表达式及运算符

    C#表达式 表达式,把变量.字面值与运算符组合起来,就创建表达式,是计算的基本构件.字面值:是源代码中键入的数字.字符串,表示指定类型的值.常用有几种:整数.实数.字符.字符串. 整数字面量[也能使用 ...

  9. CSS Secrets 翻译笔记 01: CSS coding tips

    .firDemoButton{ padding: 6px 16px; border: 1px solid #446d88; background: #58a linear-gradient(#77a0 ...

  10. vue之导入Bootstrap和Jquery

    Vue引入bootstrap主要有两种方法 方法一:在main.js中引入,此方法导入的bootstrap中对于html,body的一些预设置的css样式可能无效. 一.引入jQuery 在当前项目的 ...