涂色:(日文题目,自己翻译成了中文)为了宣传信息竞赛,要在长方形的三合板上喷油漆来制作招牌。三合板上不需要涂色的部分预先贴好了护板。被护板隔开的区域要涂上不同的颜色,比如上图就应该涂上5种颜色。

请编写一个程序计算涂色数量,输入数据中,保证看板不会被护板全部遮住,并且护板的边一定是水平或垂直的。

输入:

第一个数是宽w(1 ≤ w ≤ 1000000),第二个数是高h(1 ≤ h ≤ 1000000)。

第二行是护板的数量n(1 ≤ n ≤ 1000),接着n行是每个护板的左下角坐标 (x1 , y1 )和右上角坐标 (x2 , y2 ),用空格隔开: x1 , y1 , x2 , y2 (0 ≤ x1< x2 ≤ w, 0 ≤ y1 < y2 ≤ h 都是整数)

招牌的坐标系如下,左下角是 (0, 0) ,右上角是(w, h) , 测试集中的30%都满足w ≤ 100, h ≤ 100, n ≤ 100。

输出:

一个整数,代表涂色数量。

使用坐标离散化求解。

坐标离散化的思想是:当坐标范围很大而坐标数量很少时,可以考虑把所有用到的横坐标排序,然后用每个坐标对应的下标来更新坐标位置。

举例来说:

这个例子中的用到的横坐标有1,2,4,5,6,7,9,10,11,12,13,14。

那么横坐标对(1,5)就可以转化为(0,3)。节省了一位空间,这个节省在空隙变大后会越来越明显。

通过坐标离散化,通常时间复杂度就可以降到令人满意的程度了。

这里使用了imos法,进一步优化时间复杂度。

接下来是代码,来自http://www.hankcs.com/program/algorithm/aoj-0531-paint-color.html

  1. #include<iostream>
  2. #include<vector>
  3. #include<algorithm>
  4. #include<queue>
  5. #include <cstring>
  6. #define MAX_N 1000 + 16
  7.  
  8. using namespace std;
  9.  
  10. int N, H, W;
  11. int X1[MAX_N], X2[MAX_N], Y1[MAX_N], Y2[MAX_N];
  12. int fld[ * MAX_N][ * MAX_N], // 填充遍历用,代表坐标(i, j)处是否空白(压缩后)
  13. dx[] = { , -, , }, dy[] = { , , , - };
  14.  
  15. // 压缩坐标,将坐标的值变成“这是第几种值”,返回一共有几种坐标
  16. int compress(int *x1, int *x2, int w)
  17. {
  18. vector<int>xs;
  19.  
  20. for (int i = ; i < N; ++i)
  21. {
  22. int tx1 = x1[i], tx2 = x2[i];
  23. if ( <= tx1 && tx1 < w) xs.push_back(tx1);
  24. if ( <= tx2 && tx2 < w) xs.push_back(tx2);
  25. }
  26. xs.push_back();
  27. xs.push_back(w);
  28. sort(xs.begin(), xs.end());
  29. xs.erase(unique(xs.begin(), xs.end()), xs.end());
  30. for (int i = ; i < N; ++i)
  31. {
  32. x1[i] = find(xs.begin(), xs.end(), x1[i]) - xs.begin();
  33. x2[i] = find(xs.begin(), xs.end(), x2[i]) - xs.begin();
  34. }
  35. return xs.size() - ;
  36. }
  37.  
  38. int bfs()
  39. {
  40. int ans = ;
  41. for (int i = ; i < H; ++i)
  42. {
  43. for (int j = ; j < W; ++j)
  44. {
  45. if (fld[i][j]) continue;
  46. ++ans;
  47. queue<pair<int, int> >que;
  48. que.push(make_pair(j, i));
  49. while (!que.empty())
  50. {
  51. int nx = que.front().first, ny = que.front().second;
  52. que.pop();
  53.  
  54. for (int i = ; i < ; ++i)
  55. {
  56. int tx = nx + dx[i], ty = ny + dy[i];
  57. if (tx < || W < tx || ty < || H< ty || fld[ty][tx] > ) continue;
  58. que.push(make_pair(tx, ty));
  59. fld[ty][tx] = ;
  60. }
  61. }
  62. }
  63. }
  64. return ans;
  65. }
  66.  
  67. ///////////////////////////SubMain//////////////////////////////////
  68. int main(int argc, char *argv[])
  69. {
  70. while (cin >> W >> H, W | H)
  71. {
  72. cin >> N;
  73. for (int i = ; i < N; ++i)
  74. {
  75. cin >> X1[i] >> Y1[i] >> X2[i] >> Y2[i];
  76. }
  77.  
  78. memset(fld, , sizeof(fld));
  79.  
  80. W = compress(X1, X2, W);
  81. H = compress(Y1, Y2, H);
  82.  
  83. // imos-法
  84. for (int i = ; i < N; i++)
  85. {
  86. fld[Y1[i]][X1[i]]++;
  87. fld[Y1[i]][X2[i]]--;
  88. fld[Y2[i]][X1[i]]--;
  89. fld[Y2[i]][X2[i]]++;
  90. }
  91. // 横向累积
  92. for (int i = ; i < H; i++)
  93. {
  94. for (int j = ; j < W; j++)
  95. {
  96. fld[i][j] += fld[i][j - ];
  97. }
  98. }
  99. // 纵向累积
  100. for (int i = ; i < H; i++)
  101. {
  102. for (int j = ; j < W; j++)
  103. {
  104. fld[i][j] += fld[i - ][j];
  105. }
  106. }// 累积完后,fld中非0部分表示有挡板
  107. cout << bfs() << endl;
  108. }
  109. return ;
  110. }
  111. ///////////////////////////End Sub//////////////////////////////////

AOJ 0531 坐标离散化的更多相关文章

  1. Aizu 0531 "Paint Color" (坐标离散化+DFS or BFS)

    传送门 题目描述: 为了宣传信息竞赛,要在长方形的三合板上喷油漆来制作招牌. 三合板上不需要涂色的部分预先贴好了护板. 被护板隔开的区域要涂上不同的颜色,比如上图就应该涂上5种颜色. 请编写一个程序计 ...

  2. Greedy:Paint Color(AOJ 0531)

    涂颜料 题目大意:在一个1000000*1000000的矩阵中放入几块木板,问你这些木板把矩阵划分成了几个区域?输入会给左下角和右上角的坐标,输入W==0且H==0结束. 这一题是书上的作业题,书上有 ...

  3. AOJ 0531:Paint Color(二维离散+imos)

    [题目链接] http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0531 [题目大意] 给出一张图,和一些矩形障碍物,求该图没被障碍物覆 ...

  4. nyoj_600:花儿朵朵(树状数组+坐标离散化)

    http://acm.nyist.net/JudgeOnline/problem.php?pid=600 只附代码好了 #include<bits/stdc++.h> using name ...

  5. 【坐标离散化】AOJ0531- Paint Color

    日文题……一开始被题目骗了以为真的要写文件? 题目大意&&解答戳:❀ #include<iostream> #include<cstdio> #include& ...

  6. hihoCoder#1079(线段树+坐标离散化)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学 ...

  7. Atlantis(坐标离散化)

    http://poj.org/problem?id=1151 题意:给出矩形的左上角坐标和右下角坐标(坐标的y轴是向下的),求出矩形面积的并.. 今天好困啊..迷迷糊糊的听会神给讲了讲,敲完之后调试了 ...

  8. nyoj 600:花儿朵朵(树状数组+坐标离散化)

    http://acm.nyist.net/JudgeOnline/problem.php?pid=600 只附代码好了 #include<bits/stdc++.h> using name ...

  9. HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

随机推荐

  1. DevExpress 14.2 批量汉化

    1.下载DevExpress_.NET_Localization_Resources_14.2汉化包 2.解压后将zh-CN或zh-CHS复制到安装目录如D:\Program Files (x86)\ ...

  2. 折半查找——Java实现

    一.查找思想 折半查找 也称为二分查找,是一种效率较高的查找方法,查找时要求表中的节点按关键字的大小排序,并且要求线性表顺序存储. 首先用要查找的关键字值(key)与中间位置结点的关键字值(arr[m ...

  3. scss-&父选择器标识符

    在使用选择器嵌套的时候有一种情况需要特别注意,先看一段scss代码实例: .text a { color: blue; :hover { color: red } } 也许写此段代码目的是为了将其编译 ...

  4. linux注册服务教程

    该说明是项目完成很久之后,整理资料时的偶然发现,当时所操作的linux为中标麒麟,需要对项目进行开机自启,对llinux还不熟悉,找不到linux中的服务自启设置.辗转多次才找到了解决方案.记录以供参 ...

  5. ArcGIS Enterprise 10.5.1 静默安装部署记录(Centos 7.2 minimal)- 4、安装 ArcGIS for Server

    安装ArcGIS for Server 解压server安装包,tar -xzvf ArcGIS_Server_Linux_1051_156429.tar.gz 切换到arcgis账户静默安装serv ...

  6. Oracle Dataguard 基本原理

    转载-http://blog.sina.com.cn/s/blog_7c5a82970101prcx.html 1.DATAGUARD原理 DATAGUARD是通过建立一个PRIMARY和STANDB ...

  7. harbor使用aws s3存储

    参考:http://www.vmtocloud.com/how-to-configure-harbor-registry-to-use-amazon-s3-storage/ s3 bucket权限:更 ...

  8. mif文件C语言生成

    1:正弦波 用函数 sin (x * π/180°) /************************************************** 正弦波 mif 生成 ********** ...

  9. 安装PYTHON PIL包

    安装pillow而不是PIL pip install pillow 参考: https://github.com/python-pillow/Pillow

  10. 如何通过一个SAPGUI屏幕反查这个屏幕对应的事务码

    假设我通过某种跳转方式打开了下图这个SAPGUI的屏幕,但我想搞清楚用哪一个事务码可以直接到达这个屏幕,而不通过繁琐的点击,应该怎么做? 步骤1,点击Order字段,按F1打开帮助界面, 点上图的图标 ...