UVa 11134 传说中的车

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

题意:在n*n的棋盘上放n个车,使得任意两个车不相互攻击,且第i个车在一个给定的矩形Ri之内。用4个整数xli,yli,xri,yri来描述第i个矩形。

思路:行和列是不影响的,也就是说第i个棋子放在第几行不会影响它的列数。这样的话我们就可以分别处理行和列。由于棋子被给定了范围,这样的话我们可以用贪心法来解决,按照ri右坐标从小到大排序,然后从左坐标开始选出最小的且未被占据的坐标。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5
 6 const int maxn = 100000;
 7
 8 int n;
 9 int ok;
10
11 int vis_row[maxn];
12 int vis_col[maxn];
13
14 int ans_row[maxn];
15 int ans_col[maxn];
16
17 struct node
18 {
19     int l, r;
20     int id;
21 }x[maxn],y[maxn];
22
23 bool cmp(node a, node b)
24 {
25     return a.r < b.r || (a.r == b.r && a.l < b.l);
26 }
27
28 void solve()
29 {
30     memset(vis_row, 0, sizeof(vis_row));
31     memset(vis_col, 0, sizeof(vis_col));
32     //处理行
33     for (int i = 0; i < n; i++)
34     {
35         ok = 0;
36         int num = x[i].id;
37         for (int j = x[i].l; j <= x[i].r; j++)
38         {
39             if (!vis_row[j])
40             {
41                 ans_row[num] = j;
42                 vis_row[j] = 1;
43                 ok = 1;
44                 break;
45             }
46         }
47         if (!ok)  return;
48     }
49
50     //处理列
51     for (int i = 0; i < n; i++)
52     {
53         ok = 0;
54         int num = y[i].id;
55         for (int j = y[i].l; j <= y[i].r; j++)
56         {
57             if (!vis_col[j])
58             {
59                 ans_col[num] = j;
60                 vis_col[j] = 1;
61                 ok = 1;
62                 break;
63             }
64         }
65         if (!ok)  return;
66     }
67 }
68
69 int main()
70 {72     while (cin >> n && n)
73     {
74         for (int i = 0; i < n; i++)
75         {
76             cin >> x[i].l >> y[i].l >> x[i].r >> y[i].r;
77             x[i].id = i;
78             y[i].id = i;
79         }
80         sort(x, x + n, cmp);
81         sort(y, y + n, cmp);
82         solve();
83         if (ok)
84         {
85             for (int i = 0; i < n; i++)
86             {
87                 cout << ans_row[i] << " " << ans_col[i] << endl;
88             }
89         }
90         else cout << "IMPOSSIBLE" << endl;
91     }
92
93     return 0;
94 }
时间: 2024-11-09 19:00:19

UVa 11134 传说中的车的相关文章

Uva 11134 传说中的车 贪心的思维

题目大意: 在一个n*n的棋盘上放置n个车,使得它们之间都不能互相攻击(任意两个车都不能同行或同列),并且,对于第i个车,限制它只能放在一个矩形区域内,(xli, yli),这个矩形的左上角顶点坐标是(xli, yli),右下角顶点坐标是 (xri, yri), 1 ≤ i ≤ n, 1 ≤ xli ≤ xri ≤ n, 1 ≤ yli ≤ yri ≤ n. 分析: 两个车相互攻击的条件是在同一行或列,可以看出,行和列是无关的,所以可以分解成两个一维问题. 问题就转化为在[1,n]选择n个数,使

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

问题来源:刘汝佳<算法竞赛入门经典--训练指南> P81: 问题描述:你的任务是在n*n(1<=n<=5000)的棋盘上放n辆车,使得任意两辆车不相互攻击,且第i辆车在一个给定的矩形R之内. 问题分析:1.题中最关键的一点是每辆车的x坐标和y坐标可以分开考虑(他们互不影响),不然会变得很复杂,则题目变成两次区间选点问题:使得每辆车在给定的范围内选一个点,任何两辆车不能选同一个点.  2.本题另外一个关键点是贪心法的选择,贪心方法:对所有点的区间,按右端点从小到大排序:每次在一个区间

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

UVA 11134 Fabled Rooks 贪心

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

UVa11134传说中的车

今天给大家说一下这道题,题意就不说了,主要说一下思路以及细节部分. 首先,从这道题来看就是求出车的坐标并且使得车之间不互相攻击且要满足车在规定的范围(矩形)之中,由于紫书说这道题考察了我们问题分解的能力, 所以我们从问题分解的角度来解决,对于问题分解,我们可以通过这种方法来简化问题,从而更好的解决,这道题而言,我们需要将横坐标与纵坐标分开, 乍一看横纵坐标怎么能分开呢?仔细想一想横纵坐标之间没有联系,所以可以分别从横.纵坐标入手来解决问题,这样我们将二维的图转化成了一维. 我们看看转换成一维后得

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

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

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(算法效率--问题分解+贪心)

题意:要求在一个N*N的棋盘上放N个车,使得它们所在的行和列均不同,而且分别处于第 i 个矩形中. 解法:问题分解+贪心. 由于行.列不相关,所以可以先把行和列均不同的问题分解为2个“在区间[1,n]中选择n个不同的整数,使得第 i 个整数在[Li,Ri]内”的问题. 接下来的贪心很重要:先使区间R从小到大排序,再L.这样在每个合法区间段中尽量往左边选数的情况下,就能保证每个区间的右边一段是灵活合法的,而若R1=R2,由于是从左开始填数,这并不影响.反正我是没有找到反例的......而不像我(

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

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