zoukankan      html  css  js  c++  java
  • UVA 11134 Fabled Rooks

    https://vjudge.net/problem/UVA-11134

    题目

    你的任务是在 $n imes n$ 的棋盘上放 $n$ 个车,使得任意两个车不互相攻击,且第 $i$ 个车在一个给定的矩形 $R_i$ 之内。用4个整数 $xl_i, yl_i, xr_i, yr_i (1leqslant xl_ileqslant xr_i leqslant n, 1leqslant yl_i leqslant yr_i leqslant n)$ 描述第i个矩形,其中 $(xl_i, yl_i)$ 是左上角的坐标, $(xr_i, yr_i)$ 是右下角坐标,则第 $i$ 个车的位置 $(x,y)$ 必须满足 $xl_ileqslant x leqslant xr_i, yl_ileqslant y leqslant yr_i$。如果无解,输出IMPOSSIBLE;否则输出 $n$ 行,依次为第 $1,2,cdots,n$ 个车的坐标。

    题解

    终于不做搜索了!

    贪心……

    将两个维度分开

    法1:

    将每个区间按左端点从小到大排序

    1.l1<l2时,l1到min(r1,l2)的范围内随便选,不会丢解,因此下面不再考虑左端点不等的情况

    2.l1=l2时,需要考虑r1和r2的关系

    显然先选r2小的……

    如果按照这个策略还会出错,因为每次选择后每个区间能选的部分都会缩小一截,因为我们之前考虑的全是能选的区间……

    解决方法是选择一个点后,把所有左端点相等的区间的左端点向后移动一个单位,然后再次排序……

    由于重新排序有点麻烦,因此可以使用优先队列(堆)

    法2:

    将每个区间按右端点大小排序

    显然先选右端点小的……

    然后从左至右依次尝试……需要一个数组记录每个点是否选择

    可以验证从左至右不会丢解

    (感觉像是知道了答案编过程……还是记下,防止以后忘记)

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define REP(r,x,y) for(register int r=(x); r<(y); r++)
    #define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
    #ifdef sahdsg
    #define DBG(...) printf(__VA_ARGS__)
    #else
    #define DBG(...)
    #endif
    
    struct node {
    	int xl,yl,xr,yr;
    	int id;
    } nodes[5007];
    inline bool cmp1(const node& n1, const node &n2) {
    	return n1.xr<n2.xr || (n1.xr==n2.xr && n1.xl<n2.xl);
    }
    inline bool cmp2(const node& n1, const node &n2) {
    	return n1.yr<n2.yr || (n1.yr==n2.yr && n1.yl<n2.yl);
    }
    bool visx[5007];
    bool visy[5007];
    int main() {
    	#ifdef sahdsg
    	freopen("in.txt", "r", stdin);
    	#endif
    	int n;
    	while(~scanf("%d", &n) && n) {
    		int ans[5007][2];
    		memset(visx,0,sizeof visx);
    		memset(visy,0,sizeof visy);
    		
    		REP(i,0,n) {
    			nodes[i].id=i;
    			scanf("%d%d%d%d",
    				&nodes[i].xl,
    				&nodes[i].yl,
    				&nodes[i].xr,
    				&nodes[i].yr);
    		}
    		sort(nodes,nodes+n,cmp1);
    		REP(i,0,n) {
    			bool f=true;
    			REPE(j,nodes[i].xl,nodes[i].xr) {
    				if(!visx[j]) {
    					visx[j]=1;
    					f=false;
    					ans[nodes[i].id][0]=j;
    					break;
    				}
    			}
    			if(f) {
    				goto wa;
    			}
    		}
    		sort(nodes,nodes+n,cmp2);
    		REP(i,0,n) {
    			bool f=true;
    			REPE(j,nodes[i].yl,nodes[i].yr) {
    				if(!visy[j]) {
    					visy[j]=1;
    					f=false;
    					ans[nodes[i].id][1]=j;
    					break;
    				}
    			}
    			if(f) {
    				goto wa;
    			}
    		}
    		REP(i,0,n) {
    			printf("%d %d
    ", ans[i][0], ans[i][1]);
    		}
    		
    		continue;
    		wa:;
    		puts("IMPOSSIBLE");
    		
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    初认识AngularJS
    (imcomplete) UVa 10127 Ones
    UVa 10061 How many zero's and how many digits?
    UVa 11728 Alternate Task
    UVa 11490 Just Another Problem
    UVa 10673 Play with Floor and Ceil
    JSON对象和字符串的收发(JS客户端用typeof()进行判断非常重要)
    HTML.ActionLink 和 Url.Action 的区别
    EASYUI TREE得到当前节点数据的GETDATA方法
    jqueery easyui tree把已选中的节点数据拼成json或者数组(非常重要)
  • 原文地址:https://www.cnblogs.com/sahdsg/p/10479634.html
Copyright © 2011-2022 走看看