UVA11134- Fabled Rooks

题目链接

题意:在n*n棋盘上放n辆车,使得任意两辆车不相互攻击,且第i辆车在一个给定的矩形之内。

思路:刚开始以为是n皇后的问题,但是本题只要水平和竖直才能攻击到,并没有斜线的约束。所以可以判断出行和列是互相没有影响的,那么只要分别对行和列进行贪心操作,先按照左端点值从小到大排序,然后用优先队列维护,先处理右端点小的。

做法与这题类似 UVA1422

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

const int MAXN = 5005;

struct Car{
    int l, r, id;
    friend bool operator < (const Car a, const Car b) {
        return a.r > b.r;
    }
}x[MAXN], y[MAXN], c[MAXN];

int n;

int cmp(Car a, Car b) {
    return a.l < b.l;
}

int judge(Car *cur, int flag) {
    sort(cur, cur + n, cmp);
    priority_queue<Car> q;
    Car state;

    int cnt = 0;
    for (int i = 0; i < n; i++) {
        while (cnt < n && cur[cnt].l <= i + 1)
            q.push(cur[cnt++]);
        if (q.empty()) {
            return false;
        }
        state = q.top();
        q.pop();
        if (state.r < i + 1) {
            return false;
        }
        if (flag == 0)
            c[state.id].l = i + 1;
        else
            c[state.id].r = i + 1;
    }
    return true;
}

void outPut() {
    for (int i = 0; i < n; i++)
        printf("%d %d\n", c[i].l, c[i].r);
}

int main() {
    while (scanf("%d", &n) && n) {
        for (int i = 0; i < n; i++) {
            scanf("%d%d%d%d", &x[i].l, &y[i].l, &x[i].r, &y[i].r);
            x[i].id = y[i].id = i;
        }
        if (judge(x, 0) && judge(y, 1))
            outPut();
        else
            printf("IMPOSSIBLE\n");
    }
    return 0;
}

UVA11134- Fabled Rooks,布布扣,bubuko.com

时间: 2024-08-17 10:33:59

UVA11134- Fabled Rooks的相关文章

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

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

UVa11134 Fabled Rooks (问题分解+贪心)

链接:http://vjudge.net/problem/34086 分析:两个车相互攻击的条件是出于同一行或者同一列,因此不相互攻击的条件就是不在同一行,也不在同一列.可以看出:行和列是无关的,因此可以把原题分解成两个一维问题.把行区间和列区间拆开,用一个index变量记录行区间和列区间属于哪一个车的进行编号,假设车的行区间为[a,b],将所有行区间按b的值从小到大排序,用贪心的思想,从排好序的第一个区间开始,优先放在行序号小的位置,列区间的处理方法与上述行的处理方法相同.最后按编号将行和列的

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

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

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

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

问题来源:刘汝佳<算法竞赛入门经典--训练指南> P81: 问题描述:你的任务是在n*n(1<=n<=5000)的棋盘上放n辆车,使得任意两辆车不相互攻击,且第i辆车在一个给定的矩形R之内. 问题分析:1.题中最关键的一点是每辆车的x坐标和y坐标可以分开考虑(他们互不影响),不然会变得很复杂,则题目变成两次区间选点问题:使得每辆车在给定的范围内选一个点,任何两辆车不能选同一个点.  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(主要在贪心方法及其实现)

#用到了贪心方法. #这个贪心刚开始想错了方法,后来想到了新的方法,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(贪心 / 二分图 + 线段树优化连边)

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

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