UVa 11134 贪心
2015-12-30 18:24
169 查看
【题目链接】
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34086
【解题报告】
题目大意:
在N*N的棋盘里放N个车,使彼此不互相攻击(即不同行,不同列),每个车可以放在一个子矩阵里(给出矩阵左上角,右下角的坐标),请给出任意一种放车的方案,如果不存在,输出”IMPOSSIBLE”。
这题的贪心解法还是很值得认真体会的。
首先,行和列不相互影响,可以分开考虑,这点应该大家都知道,并没有什么难度,那么问题转化为:
这题我们很容易这样想:每个车的摆放位置对应一条线段,那么我们把n条线段从小到大排个序,然后从左到右依次摆放。怎么排序呢?
左端点优先?
那么(1,3),(1,3),(2,2)这种情况就会输出impossible,问题在哪里呢?
原因在于,我们在前面选了一条右端点靠后的,也就是说可以放在当前位置,也可以放在更后面的位置的线段,那么可能后面的线段就没有位置可以放了。
所以我们需要修正一下算法:每次挑一条对右边影响最小的线段,先把他的位置确定了。做法是:右端点优先排序。注意我们这么做的前提是:从左到右遍历线段。
这里还存在一个问题,就是是不是第i条线段就可以放第i个点。容易想到,如果是(1,3)(1,3)(2,2)这样的线段,那么我们应当先把2这个位置放了,也就是说,第一条线段对应的点是第二个。所以不确定一条线段应该放在哪个点上,我们就应该遍历这条线段上的点,第一个还没有放车的点就是当前线段应该放车的点。
【参考代码】
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34086
【解题报告】
题目大意:
在N*N的棋盘里放N个车,使彼此不互相攻击(即不同行,不同列),每个车可以放在一个子矩阵里(给出矩阵左上角,右下角的坐标),请给出任意一种放车的方案,如果不存在,输出”IMPOSSIBLE”。
这题的贪心解法还是很值得认真体会的。
首先,行和列不相互影响,可以分开考虑,这点应该大家都知道,并没有什么难度,那么问题转化为:
给出一条线上n个位置,把n个不同的车放进去,每个车有一个摆放区间,求一个方案。
这题我们很容易这样想:每个车的摆放位置对应一条线段,那么我们把n条线段从小到大排个序,然后从左到右依次摆放。怎么排序呢?
左端点优先?
那么(1,3),(1,3),(2,2)这种情况就会输出impossible,问题在哪里呢?
原因在于,我们在前面选了一条右端点靠后的,也就是说可以放在当前位置,也可以放在更后面的位置的线段,那么可能后面的线段就没有位置可以放了。
所以我们需要修正一下算法:每次挑一条对右边影响最小的线段,先把他的位置确定了。做法是:右端点优先排序。注意我们这么做的前提是:从左到右遍历线段。
这里还存在一个问题,就是是不是第i条线段就可以放第i个点。容易想到,如果是(1,3)(1,3)(2,2)这样的线段,那么我们应当先把2这个位置放了,也就是说,第一条线段对应的点是第二个。所以不确定一条线段应该放在哪个点上,我们就应该遍历这条线段上的点,第一个还没有放车的点就是当前线段应该放车的点。
【参考代码】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=5000+100; int N; struct Line{ int p0,p1,pos; int r,c; void sets( int p0, int p1, int pos ){ this->p0=p0; this->p1=p1; this->pos=pos; } }; int cmp1( Line a, Line b ) { return a.p1<b.p1 || ( a.p1==b.p1 && a.p0<b.p0 ); } int cmp2( Line a, Line b ){ return a.pos<b.pos; } Line row[maxn],column[maxn]; void solve() { int visr[maxn],visc[maxn]; memset( visr, 0, sizeof visr ); memset( visc,0,sizeof visc ); for( int i=1; i<=N; i++ ) { bool ok=false; for( int j=row[i].p0; j<=row[i].p1; j++ ) { if( !visr[j] ) { visr[j]=1; row[i].r=j; ok=true; break; } } if( !ok ) { printf( "IMPOSSIBLE\n" ); return; } ok=false; for( int j=column[i].p0; j<=column[i].p1; j++ ) { if( !visc[j] ) { visc[j]=1; column[i].c=j; ok=true; break; } } if( !ok ) { printf( "IMPOSSIBLE\n" ); return; } } sort( row+1, row+1+N, cmp2 ); sort( column+1, column+1+N,cmp2 ); for( int i=1; i<=N; i++ ) { printf( "%d %d\n",row[i].r,column[i].c ); } } int main() { while( ~scanf( "%d",&N ) && N ) { for( int i=1; i<=N; i++ ) { int x1,y1,x2,y2; scanf( "%d%d%d%d",&x1,&y1,&x2,&y2 ); row[i].sets( x1,x2,i ); column[i].sets( y1,y2,i ); } sort( row+1,row+N+1,cmp1 ); sort( column+1,column+1+N,cmp1 ); solve(); } return 0; }
相关文章推荐
- 带参数的多线程
- Android动画(一)
- Linux头文件
- iOS中UITextField禁止粘贴、禁止选择、禁止全选
- 我的编程之路(二十五) 上海的老同学
- Centos7.0下命令行模式安装Nginx
- 检索建议
- 游戏结束进入wingame不能timout不然会不停增加
- C++编程思想学习笔记---第15章 多态性和虚函数
- c# 使用Button和Panel 设计伸缩面板控件
- web项目引入extjs小例子
- U盘安装CentOS7系统 提示No Caching mode page found /dev/root does not exist错误的解决方法
- Android中Menu的基本用法
- Android 下雪动画
- SetPriorityClass
- linux网络编程常用头文件
- Qt的Model/View Framework解析(数据是从真正的“肉(raw)”里取得,Model提供肉,所以读写文件、操作数据库、网络通讯等一系列与数据打交道的工作就在model中做了)
- flex datagrid 换行
- 说说arcGIS for Android
- Error: "select_city_zzdw" is not translated in "zh" (Chinese) [MissingTranslation]