We would like to place n rooks, 1 n 5000, on a n n
board subject to the following restrictions
• The i-th rook can only be placed within the rectan-
gle given by its left-upper corner (xli; yli) and its right-
lower corner (xri; yri), where 1 i n, 1 xli
xri n, 1 yli yri n.
• No two rooks can attack each other, that is no two rooks
can occupy the same column or the same row.
Input
The input consists of several test cases. The rst line of each
of them contains one integer number, n, the side of the board. n lines follow giving the rectangles
where the rooks can be placed as described above. The i-th line among them gives xli, yli, xri, and
yri. The input le is terminated with the integer `0' on a line by itself.
Output
Your task is to nd such a placing of rooks that the above conditions are satised and then output n
lines each giving the position of a rook in order in which their rectangles appeared in the input. If there
are multiple solutions, any one will do. Output `IMPOSSIBLE' if there is no such placing of the rooks.


因为行和列并没有什么关系,所以只要把问题分成两个,如果都能满足,再进行配对即可。

那么问题就变成了在[1,n]上有n个区间,把n个整数恰好不重不漏地分配到每个区间。

很明显用贪心。

 #include<cstdio>
#include<cstring>
struct qj
{
int l,r,num;
}q1,q2;
qj a1[],a2[];
int p1[],p2[],n;
bool xy(qj a,qj b)
{
return a.l<b.l||(a.l==b.l&&a.r<b.r);
}
void st1(int l,int r)
{
int i,j,k;
qj mid=a1[(l+r)/];
i=l;
j=r;
do
{
while (xy(a1[i],mid)) i++;
while (xy(mid,a1[j])) j--;
if (i<=j)
{
p1[a1[i].num]=j;
p1[a1[j].num]=i;
q1=a1[i];
a1[i]=a1[j];
a1[j]=q1;
i++;
j--;
}
}
while (i<=j);
if (l<j) st1(l,j);
if (i<r) st1(i,r);
}
void st2(int l,int r)
{
int i,j,k;
qj mid=a2[(l+r)/];
i=l;
j=r;
do
{
while (xy(a2[i],mid)) i++;
while (xy(mid,a2[j])) j--;
if (i<=j)
{
p2[a2[i].num]=j;
p2[a2[j].num]=i;
q2=a2[i];
a2[i]=a2[j];
a2[j]=q2;
i++;
j--;
}
}
while (i<=j);
if (l<j) st2(l,j);
if (i<r) st2(i,r);
}
int main()
{
int i,j,k,m,p,q,x,y,z;
bool ok;
while (scanf("%d",&n)&&n)
{
for (i=;i<=n;i++)
{
scanf("%d%d%d%d",&q1.l,&q2.l,&q1.r,&q2.r);
p1[i]=p2[i]=q1.num=q2.num=i;
a1[i]=q1;
a2[i]=q2;
}
st1(,n);
st2(,n);
ok=;
for (i=;i<=n;i++)
if (a1[i].l>i||a1[i].r<i||a2[i].l>i||a2[i].r<i)
{
ok=;
break;
}
if (ok)
for (i=;i<=n;i++)
printf("%d %d\n",p1[i],p2[i]);
else
printf("IMPOSSIBLE\n");
}
}

以上是经典的错误答案。(反正我开始就是这么错的)

把区间按左端点排序,第i个区间放整数i。

反例:[1,1],[1,3],[2,2]。照这个贪心思路找不到解。

 #include<cstdio>
#include<cstring>
#define MS(a) memset(a,0,sizeof(a))
int l1[],r1[],l2[],r2[],p1[],p2[];
int main()
{
int i,j,k,m,n,p,q1,q2,x,y,z,min1,min2;
bool ok;
while (scanf("%d",&n)&&n)
{
MS(p1);
MS(p2);
for (i=;i<=n;i++)
scanf("%d%d%d%d",&l1[i],&l2[i],&r1[i],&r2[i]);
ok=;
for (i=;i<=n;i++)
{
q1=q2=-;
min1=min2=;
for (j=;j<=n;j++)
{
if (p1[j]==&&l1[j]<=i&&r1[j]>=i&&r1[j]<min1)
{
q1=j;
min1=r1[j];
}
if (p2[j]==&&l2[j]<=i&&r2[j]>=i&&r2[j]<min2)
{
q2=j;
min2=r2[j];
}
}
if (q1==-||q2==-)
{
ok=;
break;
}
p1[q1]=i;
p2[q2]=i;
}
if (ok)
for (i=;i<=n;i++)
printf("%d %d\n",p1[i],p2[i]);
else
printf("IMPOSSIBLE\n");
}
}

正解:把按顺序枚举区间变成按顺序枚举点。对于每个点,找到它能放的、右端点最小的区间。

若不取这个区间而取另一个右端点更大的区间,会让之后的点选择变少。

uva 11134 fabled rooks (贪心)——yhx的更多相关文章

  1. UVA - 11134 Fabled Rooks[贪心 问题分解]

    UVA - 11134 Fabled Rooks We would like to place n rooks, 1 ≤ n ≤ 5000, on a n × n board subject to t ...

  2. UVA 11134 Fabled Rooks 贪心

    题目链接:UVA - 11134 题意描述:在一个n*n(1<=n<=5000)的棋盘上放置n个车,每个车都只能在给定的一个矩形里放置,使其n个车两两不在同一行和同一列,判断并给出解决方案 ...

  3. UVA 11134 - Fabled Rooks(贪心+优先队列)

    We would like to place  n  rooks, 1 ≤  n  ≤ 5000, on a  n×n  board subject to the following restrict ...

  4. uva 11134 - Fabled Rooks(问题转换+优先队列)

    题目链接:uva 11134 - Fabled Rooks 题目大意:给出n,表示要在n*n的矩阵上放置n个车,并且保证第i辆车在第i个区间上,每个区间给出左上角和右小角的坐标.另要求任意两个车之间不 ...

  5. UVa 11134 - Fabled Rooks 优先队列,贪心 难度: 0

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  6. UVa 11134 Fabled Rooks(贪心)

    题目链接  题意  在n*n的棋盘上的n个指定区间上各放1个'车’ , 使他们相互不攻击(不在同行或同列),输出一种可能的方法. 分析 每行每列都必须放车,把行列分开看,若行和列同时有解,则问题有解. ...

  7. UVA 11134 Fabled Rooks(贪心的妙用+memset误用警示)

    题目链接: https://cn.vjudge.net/problem/UVA-11134 /* 问题 输入棋盘的规模和车的数量n(1=<n<=5000),接着输入n辆车的所能在的矩阵的范 ...

  8. UVa 11134 Fabled Rooks (贪心+问题分解)

    题意:在一个n*n的棋盘上放n个车,让它们不互相攻击,并且第i辆车在给定的小矩形内. 析:说实话,一看这个题真是没思路,后来看了分析,原来这个列和行是没有任何关系的,我们可以分开看, 把它变成两个一维 ...

  9. UVA - 11134 Fabled Rooks问题分解,贪心

    题目:点击打开题目链接 思路:为了满足所有的车不能相互攻击,就要保证所有的车不同行不同列,于是可以发现,行与列是无关的,因此题目可以拆解为两个一维问题,即在区间[1-n]之间选择n个不同的整数,使得第 ...

随机推荐

  1. 【jQuery基础学习】02 jQuery的DOM操作

    DOM操作分为3个方面: DOM Core    任何一种支持DOM Core的语言都可以使用它,比如getElementById就是DOM Core操作 HTML-DOM  只能用来处理web文档 ...

  2. csharp:Dapper Sample

    You can find Dapper on Google Code here: http://code.google.com/p/dapper-dot-net/ and the GitHub dis ...

  3. mysql学习笔记 第八天

    where,group by,having重新详解 where的用法: where与in的配合使用,in(值1,值2,...)表示结果在值1,值2,...其中任何一个. 聚合函数和group by的用 ...

  4. STL---Codeforces675D Tree Construction(二叉树节点的父亲节点)

    Description During the programming classes Vasya was assigned a difficult problem. However, he doesn ...

  5. 怎样让js循环重复执行过程

    setInterval(function(){ cc();},60000);setInterval是每隔一分钟就执行一次方法体,主要特点是循环不断的执行.而setTimeout是执行一次就不会继续执行 ...

  6. jQuery.Cookie.js用法

    jQuery.Cookie.js:一个轻量级的cookie插件,可以读取.写入.删除cookie. 一.使用方法 引入jQuery与jQuery.Cookie.js插件 <script src= ...

  7. 使用sublime text 2 版本至今我所遇到的问题及解决方法

    1.汉化:下载汉化包 .打开程序Preference下的浏览包文件夹.将解压的程序包粘贴进包文件夹2.破解:标题栏上面有带(unregistered)表示还没有注册: 打开HELP→Enter lic ...

  8. 高性能JS笔记1——加载执行

    一.脚本位置 1.Script标签尽可能放到Body底部,以减少脚本文件下载对整个页面UI渲染的影响. 2.Script标签永远不要紧跟Link标签后面. 二.组织脚本 1.合并多个文件在一个Scri ...

  9. 用Path来绘制一些图形

    Path是android中用来封装几何学路径的一个类,因为Path在图形绘制上占的比重还是相当大的.你可以用它来绘制各种样式的几何图形,做图表什么的都可以. 一.画线段 1.1 lineT(float ...

  10. 深入了解Activity-生命周期

    一 介绍 Activity是android中使用最为频繁的组件,在官方文档中是这样描述的:An activity is a single, focused thing that the user ca ...