[SMOJ1864]圆桌会议
来源:互联网 发布:txt阅读器 for mac 编辑:程序博客网 时间:2024/05/22 08:12
这题做法比较多,最起码有四种:双路 DP、二分+贪心、二分+网络流和直接贪心。
在介绍各种做法之前首先明确一条基本事实,最优方案一定是呈单峰状排列的。即对于从小到大排好序的
解法一:双路 DP。
这里的思想其实跟省赛前集训做过的“变形合唱队形”一题很类似,都是先确定好一个中心,然后向两边插入。如图:
将最高点摆好,两边不断从上到下摆编号递减(显然身高也递减)的点。设左边摆到了第
不妨用
最终的答案就是
但这样仅仅算出了最小的最大身高差。如何输出字典序最小的方案呢?
显然,要令字典序最小,我们当然希望尽可能按从小到大输出。但是,有时候为了满足身高差的限制,不得不进行必要的调整,将点放到后半段去。
这里就有一种很巧妙的方法,可以判断点能否放在前半段,使身高差限制仍然成立。那就是:枚举+DP。听起来很暴力,但数据范围比较小,并不会有问题。
具体地,一开始尝试将
总结一下,其实从中可以归纳出字典序一类问题的一种通用方法:逐一尝试。当然不是指枚举出所有可能的序列,而是尽量尝试放更优的,并判断能否这样放。
解法二:二分+贪心
不难理解,这题的答案显然是具有单调性的,因此完全可以二分答案。现在的问题是,对于一个被二分到的最大身高差
可以这样操作:交替插入前半段和后半段的值。例如:首先将
需要注意的是,最终放置完之后还需要检查一下整个序列的合法性。即对于任意的
另外,这样得到的序列,不仅适用于检查,而且也一定是最终输出时字典序最小的。
解法三:二分+网络流
在二分时,除了可以贪心判断之外,还可以跑一遍最大流。构图方法如下:
将每个点复制一份,就得到了一个二分图。若
为什么可以这样构图呢?我们不妨将一条
还可以有另外一种构图方法:将每个点
至于方案的输出,则可以参考解法一和解法二。
解法四:直接贪心。
不妨考虑从左到右一个一个插入序列中。可以发现,对于前三个人,无论如何安排,其最小差值总是一定的,都是
这样就可以求出最小的差值,之后的方案输出参考解法一和解法二即可。
下面的代码中,求身高差部分是解法四,但字典序输出与上面两种有所不同,在这篇博客中有详细的讲解,可以参考。
参考代码:
//1864.cpp#include <algorithm>#include <cstdio>#include <cstdlib>&35;#35;include <cstring>#include <iostream>#include <deque>using namespace std;const int MAXN = 50 + 10;int N;int h[MAXN], ans[MAXN];bool flag[MAXN];int main(void) { freopen("1864.in", "r", stdin); freopen("1864.out", "w", stdout); int ng; scanf("%d", &ng); while (ng--) { int N; scanf("%d", &N); for (int i = 0; i < N; i++) scanf("%d", &h[i]); sort(h, h + N); int diff = h[2] - h[0]; for (int i = 1; i + 2 < N; i++) diff = max(diff, h[i + 2] - h[i]);// printf("%d\n", diff); memset(flag, false, sizeof flag); for (int i = 0, j = 0; i < N; i++) if (h[i] - h[j] > diff) flag[j = --i] = true; //当超过身高差时,将 (i-1) 放到后面 int front = 0, rear = N - 1; for (int i = 0; i < N; i++) if (flag[i]) ans[rear--] = h[i]; else ans[front++] = h[i]; for (int i = 0; i < N; i++) printf("%d ", ans[i]); putchar('\n'); } return 0;}
总结一下,这题的一题多解都非常妙。特别是贪心,越做题才越发现它的神奇之处。有的情况下,贪心的策略不一定是唯一的,但一定要本着有理有据的原则,最好能够有相对严谨的证明。总的来说,还是要靠多练习,归纳一些方法,找找感觉吧。
- [SMOJ1864]圆桌会议
- 圆桌会议
- 圆桌会议
- 圆桌会议
- 圆桌会议
- 圆桌会议:
- 圆桌会议
- 圆桌会议
- 圆桌会议
- 圆桌会议
- 圆桌会议
- oracle2009圆桌会议
- hdu1214-圆桌会议
- hdu-圆桌会议
- ACM:圆桌会议
- hdu1214 圆桌会议
- 圆桌会议(数学题)
- hdu1214 圆桌会议
- Java 工具类
- HTTP断点续传
- for循环(笔记整理)
- 调试拷贝赋值运算符和析构函数什么时候起作用
- 最常用正则表达式,你要的都在这里了
- [SMOJ1864]圆桌会议
- java 表格导出至Excel
- win 10 下Jmeter启动报版本错误 —— 解决
- Android GridView实现动画效果实现代码
- Java笔记:字符串
- 数据类型转换之 int 与 LPCTSTR
- 1-html-基础
- hdu 6140 Hybrid Crystals
- 全排序dfs深搜回溯法