博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UVA 11134 FabledRooks 传说中的车 (问题分解)
阅读量:4946 次
发布时间:2019-06-11

本文共 2537 字,大约阅读时间需要 8 分钟。

摘要:贪心,问题分解。

因为行列无关,所以这个二维问题可以分解成两个一维问题。

优先队列实现:类似区间点覆盖的问题,先按照左端点排序,相同然后在按右端点排序(灵活性小的优先选)。最优的选法,当然是要使选的这个点经过的区间越少越好,那么就选最左边的点,因为选右边可能多经过区间,一定不比选最左边的更优。选完之后,就要把选过的点last忽略,并且把包含这个点的区间做修改,这个修改是动态的,可用优先队列

71ms

#include
using namespace std;const int maxn = 5003;struct seg{ int l,r,id; seg(int L,int R) { l = L; r = R; } seg(){} bool operator < (const seg& rhs) const { return l > rhs.l || ( l == rhs.l && r > rhs.r); }};seg dim[2][maxn];int rooks[maxn][2];priority_queue
q;bool solve(int n,int d){ for(int i = 0; i < n; i++){ q.push(dim[d][i]); } int last = 0; int id = 0; while(q.size()){ seg cur = q.top(); q.pop(); if(cur.l>cur.r) return false; if(cur.l<=last) { cur.l = last + 1; q.push(cur); }else { last = cur.l; rooks[cur.id][d] = cur.l; } } return true;}int main(){ //freopen("in.txt","r",stdin); int n; seg *R = dim[0], *C = dim[1]; for(int i = 0; i < maxn; i++) dim[0][i].id = dim[1][i].id = i; while(~scanf("%d",&n)&&n){ for(int i = 0; i < n; i++){ scanf("%d%d%d%d",&R[i].l,&C[i].l,&R[i].r,&C[i].r); } if(solve(n,0)&&solve(n,1)){ for(int i = 0; i < n; i++){ printf("%d %d\n",rooks[i][0],rooks[i][1]); } }else puts("IMPOSSIBLE"); } return 0;}
优先队列

另外一种贪心,直接按照右端点排序,优先处理右端点最小的区间,因为它的灵活性最小。从左往右边选点,使当前点尽量避免经过没有选点的区间。

这样做的效率要更高

11ms

#include
using namespace std;const int maxn = 5003;struct seg{ int l,r,id; bool operator < (const seg& rhs) const { return r < rhs.r ; }};seg dim[2][maxn];int rooks[maxn][2];bool solve(int n,int d){ int last = -1; seg *Dim = dim[d]; bool vis[n+1]; memset(vis,0,sizeof(vis)); sort(Dim,Dim+n); for(int i = 0; i < n; i++){ int j; for(j = Dim[i].l; j <= Dim[i].r; j++) if(!vis[j]) { rooks[Dim[i].id][d] = j; vis[j] = true; break; } if(j>Dim[i].r) return false; } return true;}int main(){ int n; seg *R = dim[0], *C = dim[1]; while(~scanf("%d",&n)&&n){ for(int i = 0; i < n; i++){ scanf("%d%d%d%d",&R[i].l,&C[i].l,&R[i].r,&C[i].r); R[i].id = C[i].id = i; } if(solve(n,0)&&solve(n,1)){ for(int i = 0; i < n; i++){ printf("%d %d\n",rooks[i][0],rooks[i][1]); } }else puts("IMPOSSIBLE"); } return 0;}
右端排序

 

转载于:https://www.cnblogs.com/jerryRey/p/4692756.html

你可能感兴趣的文章
让ie9之前的版本支持canvas
查看>>
排序规则
查看>>
percent的用法
查看>>
Hibernate三种状态详解
查看>>
判断一个数是否是2^N次方
查看>>
打印图形
查看>>
ngx_http_core_module 模块
查看>>
两个常见的oracle索引
查看>>
实验十 指针2
查看>>
[python]pickle和cPickle
查看>>
剑指Offer--二叉树的镜像
查看>>
PAT-BASIC-1031-查验身份证
查看>>
连连看小游戏
查看>>
(180905)如何通过梯度下降法降低损失----Google机器学习速成课程笔记
查看>>
面试介绍项目经验(转)
查看>>
<metro>Google的验证
查看>>
Oracle 表的分组操作
查看>>
在OS X上的Intllij Idea中配置GlassFish
查看>>
用查表法快速转换yv12到RGB【转】
查看>>
使用公钥登录SSL
查看>>