UVA11134 传说中的车 Fabled Rooks

首先,根据数据范围,可以得到这是一题O(N2)

考虑贪心

发现行和列是不相关的,于是可以把他们分成两个一维区间问题,也就是在线段中选出点使得每个线段中都有一个点,求出方案。

先考虑尽量不对后面造成影响,也就是留后路,所以前面要尽量选靠前的,按照右端点排序,分别处理。

最后记得按原序号输出。

#include<bits/stdc++.h>
using namespace std;
int n;
bool b1[5005],b2[5005];
struct node{int x1,x2,y1,y2,x,y,ind;}a[5005];
bool cmp(node a,node b){return a.x2<b.x2;}//第一次排序
bool cmp1(node a,node b){return a.y2<b.y2;}//第二次
bool cmp2(node a,node b){return a.ind<b.ind;}//第三次
bool ccf(){//咳咳
    fill(b1,b1+n+1,0);fill(b2,b2+n+1,0);//清零使用数组
    for(int i=1;i<=n;i++){
        scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);//输入
        a[i].ind=i;记录序号
    }
    sort(a+1,a+n+1,cmp);//处理横坐标
    for(int i=1;i<=n;i++){
        int j=a[i].x1;
        for(;j<=a[i].x2;++j)//从前往后找
         if(!b1[j]){b1[j]=1,a[i].x=j;break;}
        if(j>a[i].x2)return false;//如果找不到就返回
    }
    sort(a+1,a+n+1,cmp1);//处理纵坐标
    for(int i=1;i<=n;i++){
        int j=a[i].y1;
        for(;j<=a[i].y2;++j)
         if(!b2[j]){b2[j]=1,a[i].y=j;break;}
        if(j>a[i].y2)return false;
    }
    sort(a+1,a+n+1,cmp2);//按照原序号输出
    for(int i=1;i<=n;i++)
     printf("%d %d\n",a[i].x,a[i].y);
    return true;
}
int main(){
    while(~scanf("%d",&n)&&n)
     if(!ccf())puts("IMPOSSIBLE");
} 

原文地址:https://www.cnblogs.com/coder-cjh/p/11617059.html

时间: 2024-08-28 23:28:52

UVA11134 传说中的车 Fabled Rooks的相关文章

01_传说中的车(Fabled Rooks UVa 11134 贪心问题)

问题来源:刘汝佳<算法竞赛入门经典--训练指南> P81: 问题描述:你的任务是在n*n(1<=n<=5000)的棋盘上放n辆车,使得任意两辆车不相互攻击,且第i辆车在一个给定的矩形R之内. 问题分析:1.题中最关键的一点是每辆车的x坐标和y坐标可以分开考虑(他们互不影响),不然会变得很复杂,则题目变成两次区间选点问题:使得每辆车在给定的范围内选一个点,任何两辆车不能选同一个点.  2.本题另外一个关键点是贪心法的选择,贪心方法:对所有点的区间,按右端点从小到大排序:每次在一个区间

UVa11134传说中的车

今天给大家说一下这道题,题意就不说了,主要说一下思路以及细节部分. 首先,从这道题来看就是求出车的坐标并且使得车之间不互相攻击且要满足车在规定的范围(矩形)之中,由于紫书说这道题考察了我们问题分解的能力, 所以我们从问题分解的角度来解决,对于问题分解,我们可以通过这种方法来简化问题,从而更好的解决,这道题而言,我们需要将横坐标与纵坐标分开, 乍一看横纵坐标怎么能分开呢?仔细想一想横纵坐标之间没有联系,所以可以分别从横.纵坐标入手来解决问题,这样我们将二维的图转化成了一维. 我们看看转换成一维后得

uva11134 - Fabled Rooks(问题分解,贪心法)

这道题非常好,不仅用到了把复杂问题分解为若干个熟悉的简单问题的方法,更是考察了对贪心法的理解和运用是否到位. 首先,如果直接在二维的棋盘上考虑怎么放不好弄,那么注意到x和y无关(因为两个车完全可以在同一条斜线上,这点和皇后问题不一样),那么就可以分别考虑两个一维的问题:这是一种区间选点问题,在每个区间里都只选一个点,最后这些点分别是1到n.这就联想到这样一个经典的贪心法解决的区间选点问题:数轴上有n个闭区间[ai,bi],选取尽量少的点,使得每个区间都至少含有一个点.这个问题的解决方法就是把所有

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 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

L - Fabled Rooks(中途相遇法和贪心)

Problem F: Fabled Rooks 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 rectangle given by its left-upper corner (xli, yli) and its right-lower corner (xri

UVa 11134 Fabled Rooks(贪心)

题意  在n*n的棋盘上的n个指定区间上各放1个'车'  使他们相互不攻击   输出一种可能的方法 行和列可以分开看  就变成了n个区间上选n个点的贪心问题  看行列是否都有解就行   基础的贪心问题  对每个点选择包含它的最优未使用空间 #include <bits/stdc++.h> using namespace std; const int N = 5005; int xl[N], yl[N], xr[N], yr[N], x[N], y[N], n; bool solve(int a

UVA 11134 - Fabled Rooks(贪心 / 二分图 + 线段树优化连边)

题目地址:Fabled Rooks 题目大意:n * n 的棋盘上摆了 n <=10^5 个车,让他们两两不攻击,每个车必须摆在一个给定矩形里,给出一个解决方案? 1. 贪心 由于行列互不影响, 所以可以分两遍求.第一遍确定每个车的行数,第二遍确定列数. 以行为例,若从左到右扫描,则按照区间的右端点升序排序,因为如果扫到一个位置两枚棋子都可以放,则选择右端点较小的那个(右端点大的后面还有机会). 2. 二分图匹配 有个毒瘤老师把题目改成了这样:n * n 的棋盘上摆了 n <=10^5 个车,

Fabled Rooks

Problem F: Fabled Rooks 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 rectangle given by its left-upper corner (xli, yli) and its right-lower corner (xri

uva 11134 - Fabled Rooks(主要在贪心方法及其实现)

#用到了贪心方法. #这个贪心刚开始想错了方法,后来想到了新的方法,AC 刚开始错在了按左端点升序排序并从左往右取最左端能取的格子,这个方法显然不能符合要求 比如下面这组数据: 2 1 1 3 3 1 1 3 3 2 2 2 2 错误代码: #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; struct note {