UVA 11134 Fabled Rooks (贪心)

题意:给n个矩形,要求在每个矩形里放一个战车,使得每个战车不在同一行也不再同一列

分析:在本题中行、列是无关的,可以将行、列分开来求,因此可以分成两个一维的问题,在区间[1~n]内选择n个不同的整数,使得第i个整数在闭区间[n1i,n2i]内,这是一个区间的贪心题

贪心策略:对于每一个子区间(矩形),我们先给他排序,排序的规则是按照区间长度从小到大排序,然后依次选择

贪心的正确性:因为矩形可能会出现重叠,假如先选择了大矩形的,可能会导致小矩形没有位置了。所以要从小矩形开始选

代码:

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <sstream>
#define ll long long
#define mod 1000000007
#define mod1 10001
#define mem(a) memset(a,0,sizeof(a))

using namespace std;

const int maxn = 5000 + 5 , inf = 0x3f3f3f3f ;


int visx[maxn],visy[maxn],x[maxn],y[maxn];
struct node{
    int id;
    int xl,yl,xr,yr;
}nodes[maxn];
bool cmpx (const node &rhs1,const node &rhs2){
    return rhs1.xr==rhs2.xr?rhs1.xl>rhs2.xl:rhs1.xr<rhs2.xr;
}
bool cmpy (const node &rhs1,const node &rhs2){
    return rhs1.yr==rhs2.yr?rhs1.yl>rhs2.yl:rhs1.yr<rhs2.yr;
}

void Init(){
    mem(visx),mem(visy),mem(x),mem(y);
    mem(nodes);
}

int main(){
    int n;
    while(scanf("%d",&n),n){
        Init();
        for(int i=0;i<n;i++){
            scanf("%d%d%d%d",&nodes[i].xl,&nodes[i].yl,&nodes[i].xr,&nodes[i].yr);
            nodes[i].id = i+1;
        }
        bool flag = true;
        sort(nodes,nodes+n,cmpx);
        for(int i=0;i<n;i++){
            int p = nodes[i].xl;
            int q = nodes[i].xr;
            while(visx[p]) p++;
            if(p<=q){
                visx[p] = 1;
                x[nodes[i].id] = p;
            }else{
                flag = false;
                break;
            }
        }
        if(flag){
            sort(nodes,nodes+n,cmpy);
            for(int i=0;i<n;i++){
                int p = nodes[i].yl;
                int q = nodes[i].yr;
                while(visy[p]) p++;
                if(p<=q){
                    visy[p] = 1;
                    y[nodes[i].id] = p;
                }else{
                    flag = false;
                    break;
                }
            }
        }
        if(flag)
            for(int i=1;i<=n;i++)
                printf("%d %d\n",x[i],y[i]);
        else printf("IMPOSSIBLE\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值