UVa 11134 Fabled Rooks(贪心)

题目链接 

题意 

 在n*n的棋盘上的n个指定区间上各放1个'车’ , 使他们相互不攻击(不在同行或同列),输出一种可能的方法。

 

分析

每行每列都必须放车,把行列分开看,若行和列同时有解,则问题有解。这样就变成了n个区间选n个点的贪心问题。对每个点x选择包含它的最优未使用的区间,这个最优区间就是右界最小的区间。因为在给k找最优区间时,1~k-1的最优区间都已经找好了。

 

 

#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[], int l[], int r[])  {  
    int cur, mr;  
    //mr为包含k的区间最小右界,cur为放k的最优区间  
    memset(a, -1, sizeof(int)*n);  
    for(int k = 1; k <= n; ++k)  
    {  
        cur = -1, mr = N;  
        for(int i = 0; i < n; ++i)  
            if(a[i] < 0 && l[i] <= k && r[i] < mr)  
                mr = r[cur = i];  
        if(cur < 0 || k > mr)  return 0;  
        a[cur] = k;  
    }  
    return 1;  
}  
  
int main()  
{  
    while(~scanf("%d", &n), n)  {  
        for(int i = 0; i < n; ++i)  
            scanf("%d%d%d%d", &xl[i], &yl[i], &xr[i], &yr[i]);  
  
        if(solve(x, xl, xr) && solve(y, yl, yr))  
            for(int i = 0; i < n; ++i)  
                printf("%d %d\n", x[i], y[i]);  
        else puts("IMPOSSIBLE");  
    }  
    return 0;  
}  

 

posted @ 2018-04-21 10:45  litos  阅读(195)  评论(0编辑  收藏  举报