UVa #11134 Fabled Rooks (例题8-4)
来源:互联网 发布:色情网页站 源码 wap 编辑:程序博客网 时间:2024/06/04 18:56
书中的提示很有帮助,将这道题拆成两个一维空间分开进行判断,那么就变成了贪心法的区间重叠问题
设车的摆放位置为 [a,b]。我的算法是,将所有的区间按照 b 的值从小到大排列,b相同的按照 a 从小到大排列。然后从排好序的第一个区间(即a、b最小)开始选择摆放位置。
选摆放位置的时候,从左向右扫描,一旦有某一列暂时空着(没有其他的车摆在这一列),则马上摆放在这里,然后继续摆下一个车。如果某一辆车从左向右扫描到尽头,还没有找到空着的位置,那么此组数据无解
为什么这样的贪心法可以获得正确解:
因为区间已经按照a、b排好序,所以上下相邻的两个区间的左右边界一共有几种情况:
1、b1 < b2, a1 < a2
2、b1 < b2, a1 = a2
3、 b1 < b2, a1 > a2
4、 b1 = b2, a1 < a2
5、 b1 = b2, a1 = a1
(下面所说的最左端的点,全部指代从左侧开始往右搜索,第一个没有被其他车占着的点)
对于1和4,很显然第一个区间选择最左端的点是合理的,否则将会造成浪费(后面所有的区间都不再能选到那个点,那个点将永远空着)
对于2和5,如果第一个区间不选择最左端的点,那么第二个区间可以选择最左端的点,这和我们的解法结果相同。
对于3,第一个区间的选点对第二个区间并没有直接的影响,但是却可能会对第三个、第四个...造成影响(假如将第二个区间拿走,则第一个和第三个区间可能形成1、2、4、5的情况。如果第一个区间不选择最左端的点的话,可能会对第三个区间的选点会造成浪费)。
按照这样的算法,对于所有已经摆好的区间,我们可以确定整体上已经是最紧凑的状态,没有一点浪费。所以如果到了某一个区间,发现所有的位置都无法摆放,则可以果断返回无解,因为之前摆好的车再怎么调整也无法腾出空位。
要注意的是,同样的算法不可以按照 a 的大小来排序。
举一个反例:
两个区间a和b的范围分别是 [4,9] 和 [5,8]。按照排序规则,a要排在b上面:
(a) 4 5 6 7 8 9(b) 5 6 7 8
如果此时 1-7 都已经被其他的车占领,那么a区间会选择占据 8。区间b就会返回无解。但实际上a可以占9,而b占8
如果要按照a的大小排序的话,我感觉应该反向搜索,即每次摆放在最右端的可行位置。
不经意间居然做了一道带星号的例题。。我感觉也是撞大运了
Run Time: 0.026s
#define UVa "LT8-4.11134.cpp"#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;struct Range { int l, r, order; Range(int a, int b, int c):l(a),r(b),order(c){} bool operator < (const Range& r2) const { return (r == r2.r) ? l < r2.l : r < r2.r; }};//Global Variables.int n;const int maxn = 5000 + 10;vector<Range> restrict[2];int ans[maxn][2], vis[maxn][2]; //[0] for row, [1] for col;////void print_ans() { for(int i = 0; i < n; i ++) { if(vis[i][0] != -1) ans[vis[i][0]][0] = i; if(vis[i][1] != -1) ans[vis[i][1]][1] = i; } for(int i = 0; i < n; i ++) { printf("%d %d\n", ans[i][1]+1, ans[i][0]+1); }}int solve() { for(int k = 0; k < 2; k ++) { for(int i = 0; i < n; i ++) { int l, r, order; l = restrict[k][i].l; r = restrict[k][i].r; order = restrict[k][i].order; while(l <= r && vis[l][k] != -1) { l++; } if(l > r) return 0; vis[l][k] = order; } } print_ans(); return 1;}int main() { while(scanf("%d", &n) && n) { restrict[0].clear(); restrict[1].clear(); memset(ans, -1, sizeof(ans)); memset(vis, -1, sizeof(vis)); int a, b, c, d; for(int i = 0; i < n; i ++) { scanf("%d%d%d%d", &a, &b, &c, &d); Range colRange(a-1,c-1, i); //ATTENTION. -1 applied. Range rowRange(b-1,d-1, i); restrict[0].push_back(rowRange); restrict[1].push_back(colRange); } for(int i = 0; i < 2; i ++) sort(restrict[i].begin(), restrict[i].end()); if(!solve()) { printf("IMPOSSIBLE\n"); } } return 0;}
- UVa #11134 Fabled Rooks (例题8-4)
- 例题8-4 传说中的车(Fabled Rooks, UVa 11134)
- uva 11134 Fabled Rooks
- Uva-11134-Fabled Rooks
- uva 11134 Fabled Rooks
- uva 11134 - Fabled Rooks
- UVA 11134 - Fabled Rooks
- UVa:11134 Fabled Rooks
- uva 11134 Fabled Rooks
- UVa 11134 - Fabled Rooks
- UVa 11134 Fabled Rooks
- UVA 11134 - Fabled Rooks
- Uva - 11134 - Fabled Rooks
- UVA - 11134 Fabled Rooks
- UVA 11134 Fabled Rooks
- UVA - 11134 Fabled Rooks
- UVA 11134 Fabled Rooks
- UVA 11134 Fabled Rooks
- 使用Eclipse开发Android时整个工程或第三方jar包的正确使用
- Flume-conf总结-5-http_self_to_kafka
- libevent学习五
- scheme 符号求导程序
- 应用框架的设计与实现.net平台--跨领域组件--IOC容器
- UVa #11134 Fabled Rooks (例题8-4)
- 改进的筛素数法
- Linux下查看内存使用情况方法总结
- 对网站网页进行相关的优化,提高在搜索引擎上的排名
- C# Managed DirectX中的Device类
- initramfs对应的init脚本文件,解压后可见
- Python学习:自定义对象
- 排序二叉树的中序遍历
- POJ 2774 Long Long Message && URAL 1517. Freedom of Choice(求最长重复子序列)