题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=3174

题解

其实此题并不需要那么多YY的部分。

我们考虑若干个小矮人逃出的顺序。若跳出的 \(k\) 个小矮人依次为 \(p_1, p_2, \cdots , p_k\),那么我们一定可以将他们排序,使得对于任意的 \(i < j\) 满足 \(a_i + b_i < a_j + b_j\) 且按照该顺序依然能保证 \(k\) 个小矮人全部逃出。

证明如下:

若对于任意 \(i, j\),有 \(a_i + b_i < a_j + b_j\),且 \(j\) 比 \(i\) 先逃出,那么设 \(i\) 后面所有人的高度贡献为 \(s_1\),\(i\) 与 \(j\) 之间的人的高度贡献为 \(s_2\),\(h\) 为洞深,可得:

\[a_i + a_j +b_j \geq h - s_1 - s_2 \tag{1}$$ $$a_i + b_i \geq h - s_1 \tag{2}
\]

通过 \((2)\),我们可以推得:$$a_j + a_i + b_i \geq h - s_1 - s_2 \tag{3}$$

通过 \((2)\) 以及 \(a_i + b_i < a_j + b_j\),我们可以推得:$$a_j + b_j \geq h - s_1 \tag{4}$$

由 \((3), (4)\) 可以得出:\(i\) 比 \(j\) 先逃出依然是合法的。

这样,我们就证明了排序的正确性,那么就可以先排序再 dp 了。一个比较显然的状态是,我们设 \(f_{i, j}\) 表示考虑完排序后的前 \(i\) 个人,且已经逃走的人的 \(\sum a_k\) 的值为 \(j\) 时,最多能逃走多少人。不过由于 \(\sum a_k\) 可能很大,这样定义状态并不可行,因此我们需要把状态的第二维与状态本身的意义交换一下:设 \(f_{i, j}\) 表示考虑完排序后的前 \(i\) 个人,且已经逃走了 \(j\) 个人,这 \(j\) 个人的 \(\sum a_k\) 的最小值。这样,我们就能在 \(O(n^2)\) 的时间内完成这个 dp 了。

代码

#include<bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define debug(...) fprintf(stderr, __VA_ARGS__) typedef long long ll;
typedef long double ld;
typedef unsigned int uint;
typedef pair<int, int> pii;
typedef unsigned long long ull; template<typename T> inline void read(T& x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
} template<typename T, typename... U> inline void read(T& x, U&... y) {
read(x), read(y...);
} template<typename T> inline bool checkMax(T& a, const T& b) {
return a < b ? a = b, true : false;
} template<typename T> inline bool checkMin(T& a, const T& b) {
return a > b ? a = b, true : false;
} const int N = 2e3 + 10, inf = 0x3f3f3f3f; struct State {
int x, y;
State () {}
State (int x, int y): x(x), y(y) {}
bool operator < (const State& a) const {
return x + y < a.x + a.y;
}
} s[N]; int n, f[N][N], h; int main() {
read(n);
int sa = 0;
for (register int i = 1; i <= n; ++i) {
read(s[i].x, s[i].y), sa += s[i].x;
}
sort(s + 1, s + 1 + n);
read(h);
memset(f, 0x3f, sizeof f);
f[0][0] = 0;
for (register int i = 1; i <= n; ++i) {
for (register int j = 0; j <= i; ++j) {
f[i][j] = f[i - 1][j];
}
for (register int j = 1; j <= i; ++j) {
if (sa - f[i - 1][j - 1] + s[i].y >= h) {
checkMin(f[i][j], f[i - 1][j - 1] + s[i].x);
}
}
}
int ans = 0;
for (register int i = 1; i <= n; ++i) {
if (f[n][i] < inf) {
ans = i;
}
}
printf("%d\n", ans);
return 0;
}

BZOJ3174. [TJOI2013]拯救小矮人(dp)的更多相关文章

  1. BZOJ3174:[TJOI2013]拯救小矮人(DP)

    Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人, ...

  2. BZOJ3174 Tjoi2013 拯救小矮人(贪心+DP)

    传送门 Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个 ...

  3. bzoj3174 [Tjoi2013]拯救小矮人

    Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人, ...

  4. BZOJ3174 TJOI2013 拯救小矮人 贪心、DP

    传送门 原问题等价于:先给\(n\)个人排好顺序.叠在一起,然后从顶往底能走即走,问最多能走多少人 注意到一个问题:如果存在两个人\(i,j\)满足\(a_i + b_i < a_j + b_j ...

  5. bzoj千题计划208:bzoj3174: [Tjoi2013]拯救小矮人

    http://www.lydsy.com/JudgeOnline/problem.php?id=3174 按a+b从小到大排序,a+b小的在上面,先考虑让它逃出去 正确性不会证 感性理解一下,最后一个 ...

  6. 【BZOJ-3174】拯救小矮人 贪心 + DP

    3174: [Tjoi2013]拯救小矮人 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 686  Solved: 357[Submit][Status ...

  7. BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP

    BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀 ...

  8. 【BZOJ3174】[TJOI2013]拯救小矮人(贪心,动态规划)

    [BZOJ3174][TJOI2013]拯救小矮人(贪心,动态规划) 题面 BZOJ 洛谷 题解 我们定义一个小矮人的\(A_i+B_i\)为它的逃跑能力. 我们发现,如果有两个小矮人\(x,y\), ...

  9. 贪心+DP【洛谷P4823】 [TJOI2013]拯救小矮人

    P4823 [TJOI2013]拯救小矮人 题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以 ...

随机推荐

  1. Guava包学习-Multimap

    它和上一章的MultiSet的继承结果很相似,只不过在上层的接口是Multimap不是Multiset. Multimap的特点其实就是可以包含有几个重复Key的value,你可以put进入多个不同v ...

  2. 【[HAOI2011]向量】

    靠瞎猜的数学题 首先我们先对这些向量进行一顿组合,会发现\((a,b)(a,-b)\)可以组合成\((2a,0)\),\((b,-a)(b,a)\)可以组合成\((2b,0)\),同理\((0,2a) ...

  3. MAC下常用命令的中文帮助文档(man) 出现错误

    MacdeMacBook-Pro:Desktop mac$ tar -xf manpages-zh-1.5.2.tar.bz2 MacdeMacBook-Pro:~ root# cd /Users/m ...

  4. CUDA 纹理的使用

    纹理绑定有两种,一个是绑定到线性内存就是用cudaMalloc();cudaMemcpy();开辟的内存空间,另一种是绑定到cudaMallocArray, cudaMemcpyToArray开辟到的 ...

  5. 【zigbee】【蓝牙】射频信号放大器兼容AT2401C

    现在科技产品的不断进步,智能家居方面慢慢对信号和距离方面的要求渐渐增加.深圳市动能世纪科技有限公司不断的满足客户需求,推出了一款射频信号放大器AT2401C满足客户距离信号等等的需求.并全方位技术支持 ...

  6. (转)openstack 资源查询常用 sql

    直接通过查询 openstack 数据库, 获得相应的常见查询结果 查询用户使用中主机, 及其主机对应信息 查询用户使用中存储, 及其存储对应信息 查询用户对应主机 mysql> select ...

  7. .gitignore设置不生效

    .gitignore git中,如果想要让git忽略某些文件,或不想push到远程库,不让其受版本的控制.可以使用git提供的.gitignore文件进行配置.像这样: 一般情况下,在文件还未修改前, ...

  8. 推荐一个Oracle数据库学习网站

    推荐一个我个人的Oracle数据库学习网站,比较系统性的整理,会持续更新的网站.网址: Oracle基础教程: http://www.oraclejsq.com/article/010100110.h ...

  9. css中的定位问题

    由于我最近在修改自己的网页布局,突然发现了自己对css中的定位概念还是混淆的,于是通过查官方文档,大神博客,自己实践,重新梳理了css定位的知识点.如果有不对的地方,请指正

  10. mysql当前用户user()与current_user()

    Mysql在进行登陆时,会去匹配mysql库中的user表,并赋予相应的权限,但是怎么知道我们当时的登陆的用户名及相应的权限呢? 在Mysql中,有两个函数,一个是user(),一个是current_ ...