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 (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 first 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 file is terminated with the integer ‘0’ on a line by itself.

    Output

    Your task is to find such a placing of rooks that the above conditions are satisfied 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.

    Sample Input

    8
    1122
    5788
    2255
    2255
    6386
    6385
    6388
    3678
    8
    1122
    5788
    2255
    2255
    6386
    6385
    6388
    3678
    0

    Sample Output

    11
    58
    24
    42
    73
    85
    66
    37
    11
    58
    24
    42
    73
    85
    66
    37


白书

在n*n的棋盘上面放n个车,能否使他们互相不攻击(即不能在同一行一列),并且第i个车必须落在第i的矩形范围(xl,yl, xr,yr)之内

行列可以分开求解,变成了区间问题

一开始想按r小大排序,r相同按l排序,然后依次选择行了

然而,应该是“对于每个位置,选择合法且r最小的”,这样排序并不能保证

只好n^2暴力找了

//
//  main.cpp
//  uva11134
//
//  Created by Candy on 10/17/16.
//  Copyright © 2016 Candy. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=5e3+5,INF=1e9;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
int n;
int x[N],y[N];
struct data{
    int id;
    int l1,r1,l2,r2;
}a[N];
//bool cmp1(data &x,data &y){
//    if(x.l1==y.l1) return x.r1<y.r1;
//    else return x.l1<y.l1;
//}
//bool cmp2(data &x,data &y){
//    if(x.l2==y.l2) return x.r2<y.r2;
//    return x.l2<y.l2;
//}
//bool solve(){
//    sort(a+1,a+1+n,cmp1);
//    int p=1;
//    for(int i=1;i<=n;i++){
//        //printf("hi%d %d %d %d\n",i,a[i].l1,a[i].r1,a[i].id);
//        if(a[p].l1<=i&&i<=a[p].r1) x[a[p++].id]=i;
//        else if(a[p].r1<i||a[p].l1>i) return 0;
//    }
//
//    sort(a+1,a+1+n,cmp2);
//    p=1;
//    for(int i=1;i<=n;i++){
//        //printf("ih%d %d %d %d\n",i,a[i].l2,a[i].r2,a[i].id);
//        if(a[p].l2<=i&&i<=a[p].r2) y[a[p++].id]=i;
//        else if(a[p].r2<i||a[p].l2>i) return 0;
//    }
//    return 1;
//}
bool sol(){
    memset(x,0,sizeof(x));
    memset(y,0,sizeof(y));
    for(int i=1;i<=n;i++){
        int rook=0,mnr=INF;
        for(int j=1;j<=n;j++)
            if(!x[j]&&a[j].l1<=i&&a[j].r1<mnr) rook=j,mnr=a[j].r1;
        //printf("rook1 %d\n",rook);
        if(rook==0||a[rook].r1<i) return false;
        x[rook]=i;
    }
    for(int i=1;i<=n;i++){
        int rook=0,mnr=INF;
        for(int j=1;j<=n;j++)
            if(!y[j]&&a[j].l2<=i&&a[j].r2<mnr) rook=j,mnr=a[j].r2;
        //printf("rook2 %d\n",rook);
        if(rook==0||a[rook].r2<i) return false;
        y[rook]=i;
    }
    return 1;
}
int main(int argc, const char * argv[]) {
    while((n=read())){
        for(int i=1;i<=n;i++){
            a[i].id=i;
            a[i].l1=read();a[i].l2=read();a[i].r1=read();a[i].r2=read();
        }
        if(sol()){
            for(int i=1;i<=n;i++) printf("%d %d\n",x[i],y[i]);
        }else printf("IMPOSSIBLE\n");
    }

    return 0;
}
时间: 2024-10-21 10:14:45

UVA - 11134 Fabled Rooks[贪心 问题分解]的相关文章

UVA 11134 Fabled Rooks 贪心

题目链接:UVA - 11134 题意描述:在一个n*n(1<=n<=5000)的棋盘上放置n个车,每个车都只能在给定的一个矩形里放置,使其n个车两两不在同一行和同一列,判断并给出解决方案. 算法分析:刚开始没有思路,后来看了别人的博客有了一点想法.我们把矩形的行和列分开解决,即n个车首先不能放置在同一行,然后判断n个车不能放置在同一列,如果都满足的话,即有正确的方法,否则就不行.那么怎样解决和判断在不在同一行并且是否可行呢,我们针对行而言,把这些行的坐标存入优先队列,首先取出最上面(行的标号

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 rectangle given by its left-upper corner (xli, yli) and its rightlower corner (xri, yri), where 1 ≤ i ≤

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 {

(白书训练计划)UVa 11134 Fabled Rooks(贪心)

题目地址:UVa 11134 这题因为行与列是无关的,互无影响的.所以可以将行或列分开来计算.这就相当于转化成了在期间[1,n]内选择n个不同的整数,使得第i个整数在闭区间[Li,Ri]内.这就转换成了一个贪心问题了.但是注意不能先按照左端点排序,再按右端点排序,然后尽量往左边放,比如,(1,1),(1,3),(2,2),这样是不对的,应该按右端点为主关键字排序,再按左端点为次关键字排序.看到网上的方法全都是用每次选一个数后,都要在后面的区间中删去这个数,还要用到优先队列..感觉没必要这样做..

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 个车,

Uva 11134 Fabled Rooks (问题分解 + 贪心放置)

题意: 给你n*n的棋盘,让放置n个车 使他们之间并不能相互攻击 附加条件是 给定n个车的放置区间 用左上角和右下角的坐标来表示 解题思路: 首先明确 横向的约束和纵向的约束其实并不互相影响 所以可以对横向和纵向单独求解 把问题变成两个一维的区间选点问题来求解 另外 在取点的时候 有贪心的思路在里面 对于n个区间 应该先选择区间中r最小的区间进行放置可放置的点 可以简单认为这是因为r越小的区间 其选择的灵活性就越低. 我刚开始的时候 是采取了先放置区间长度小的 在放置l小的区间 不正确. cod

uva 11134 fabled rooks (贪心)——yhx

We would like to place n rooks, 1 n 5000, on a n nboard 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

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

题目链接: https://cn.vjudge.net/problem/UVA-11134 1 /* 2 问题 输入棋盘的规模和车的数量n(1=<n<=5000),接着输入n辆车的所能在的矩阵的范围,计算并输出使得每辆车横竖都不能相互攻击 3 的摆放方法,能则输出每辆车的坐标,不能则输出"IMPOSSIBLE". 4 解题思路 想想怎么将问题分解成几个小问题,不同行不同列的话,将其分成两个一维问题,采用DFS向下搜索,搜的时候注意每个车的 5 行区间和列区间,找到一种则直接