UVa11134传说中的车

今天给大家说一下这道题,题意就不说了,主要说一下思路以及细节部分。

首先,从这道题来看就是求出车的坐标并且使得车之间不互相攻击且要满足车在规定的范围(矩形)之中,由于紫书说这道题考察了我们问题分解的能力,

所以我们从问题分解的角度来解决,对于问题分解,我们可以通过这种方法来简化问题,从而更好的解决,这道题而言,我们需要将横坐标与纵坐标分开,

乍一看横纵坐标怎么能分开呢?仔细想一想横纵坐标之间没有联系,所以可以分别从横、纵坐标入手来解决问题,这样我们将二维的图转化成了一维。

我们看看转换成一维后得到的结果,就是满足在区间内选择不重复的点,使得每个点都有对应的区间,类似于区间选点问题,所以我们要用贪心的方式来

找出解。我们在选择点时一定要满足不影响或者最小化影响后面的点的选择,这样如果都求不出来结果那么就输出IMPOSSIBLE了吧!我们怎么才能

最小化影响后面选点的情况呢?根据区间选点的思路,我们需要对每个区间的结尾x1、y1等以他们作为优先考虑的对象进行排序,为什么不能以x0、y0呢?

对于这个疑问我给出一个样例,然后大家想想就明白了。

样例如下:

3
1 1 3 3
1 1 3 3
2 2 2 2

大家想一想输出,然后看看自己的程序能不能输出正确的答案。

所以,我们确定了先按x1、y1从小到大排序,然后相同时按照x0、y0从大到小排序(想一想,为什么?),对横、纵坐标分别进行处理后我们合并输出答案就可以了。

下面是代码:

// UVa 11134
// 问题分解
/* 横与竖互不影响,所以将它们分开进行计算,这样我们将
   二维转化成为了一维,然后成为了区间选点类似的问题,贪心法进行求解。
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; 

const int maxn = 5000 + 5;
int X0[maxn], X1[maxn], Y0[maxn], Y1[maxn], rec[maxn], vis[maxn];
int r[maxn], c[maxn];   

bool cmp1(int a, int b) { // 关于x的排序
  if (X1[a] != X1[b]) return X1[a] < X1[b];
  return X0[a] > X0[b];
}

bool cmp2(int a, int b) { // 关于y的排序
  if (Y1[a] != Y1[b]) return Y1[a] < Y1[b];
  return Y0[a] > Y0[b];
}

int main() {
  int n;
  while (scanf("%d", &n) == 1 && n) {
    for (int i = 0; i < n; ++i) rec[i] = i;
    for (int i = 0; i < n; ++i)
      scanf("%d%d%d%d", &X0[i], &Y0[i], &X1[i], &Y1[i]);
    bool ok = 1;
    sort(rec, rec+n, cmp1);
    memset(vis, 0, sizeof(vis));
    int p = 0;
    while (p < n) {
      bool Vis = 0;
      for (int x = X0[rec[p]]; x <= X1[rec[p]]; ++x)
        if (!vis[x]) {
          vis[x] = Vis = 1;
          r[rec[p]] = x;
          break;
        }
      if (!Vis) ok = 0;
      p++;
    }
    sort(rec, rec+n, cmp2);
    memset(vis, 0, sizeof(vis));
    p = 0;
    while (p < n) {
      bool Vis = 0;
      for (int y = Y0[rec[p]]; y <= Y1[rec[p]]; ++y)
        if (!vis[y]) {
          vis[y] = Vis = 1;
          c[rec[p]] = y;
          break;
        }
      if (!Vis) ok = 0;
      p++;
    }
    if (!ok) printf("IMPOSSIBLE\n");
    else for (int i = 0; i < n; ++i) printf("%d %d\n", r[i], c[i]);
  }
  return 0;
}

有不懂的地方请在下方留言,我会及时回答的。

原文地址:https://www.cnblogs.com/yifeiWa/p/11217592.html

时间: 2024-10-11 16:11:57

UVa11134传说中的车的相关文章

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

【UVA11134】传说中的车

横纵坐标互不影响,所以问题转化到一维:在n个区间中每个区间选一个数,n个数都被选一次 将区间按右端点排序,枚举区间,每个区间选最靠左的没被选过的点 #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; const int MAXN=5010; int n,ansx[MAXN],ansy[MAXN]; struct Range

UVa 11134 传说中的车

https://vjudge.net/problem/UVA-11134 题意:在n*n的棋盘上放n个车,使得任意两个车不相互攻击,且第i个车在一个给定的矩形Ri之内.用4个整数xli,yli,xri,yri来描述第i个矩形. 思路:行和列是不影响的,也就是说第i个棋子放在第几行不会影响它的列数.这样的话我们就可以分别处理行和列.由于棋子被给定了范围,这样的话我们可以用贪心法来解决,按照ri右坐标从小到大排序,然后从左坐标开始选出最小的且未被占据的坐标. 1 #include<iostream>

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

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

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个数,使

第八章 高效算法设计

分治法求最大连续和 注意范围是[x,y) #include<bits/stdc++.h> using namespace std; int maxsum(int *A,int x,int y){ if(y-x==1) return A[x]; int m=x+(y-x)/2; int maxs = max(maxsum(A,x,m),maxsum(A,m,y)); int v,L,R; v=0; L=A[m-1]; for(int i=m-1;i>=x;i--) L=max(L,v+=A

uva11134 相互不攻击的车

/*uva11134在N*N(1<=N<=5000)的棋盘上放置N个车,使它们相互不攻击.但是车有划定的区间放置.求解一种方案,是的每个车能放置,没有一种满足,输出impossible思路:这种放置车的问题,一般思考到二分图最大匹配上.因为要求出到底放置到哪个位置,所以要记录下来匹配的点.我们发现行和列是可以分类讨论的(因为给定的区间是一个矩形,这样,即使选定了某一行放置,所有的列还是可供选择的)整理一下流程:例如行:对车编号1--N,对行编号1--N;如果一个车i能放置到第j行,我们在i和j

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

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

【转】【公司调查】车来了APP

http://blog.sina.com.cn/s/blog_83b10acc0102vk7k.html [APP简介] "车来了"是武汉元光科技有限公司开发的一款查询公交车实时位置的手机软件.不仅能提供公交车的到站距离.预计到站时间,还能显示整条线路的实时通行状况,让人们不再盲目等待,有效缓解人们候车的不安全感,同时改变用户出行方式.它的前身,是2012年在武汉开始爆红的“智能公交”. [创始人] 邵凌霜,武汉元光科技有限公司创始人,也是“车来了”APP的创始人.2010年1月8日,