洛谷题目链接:[USACO5.3]窗体面积Window Area

题目描述

你刚刚接手一项窗体界面工程。窗体界面还算简单,而且幸运的是,你不必显示实际的窗体。有 5 种基本操作:

创建一个新窗体

将窗体置顶

将窗体置底

删除一个窗体

输出窗体可见部分的百分比(就是,不被其它窗体覆盖的部分)。

在输入文件中,操作以如下的格式出现。

创建一个新窗体:w(I,x,y,X,Y)

将窗体置顶: t(I)

将窗体置底: b(I)

删除一个窗体:d(I)

输出窗体可见部分的百分比:s(I)

I 是每个窗体唯一的标识符,标识符可以是 'a'..'z', 'A'..'Z' 和 '0'..'9' 中的任何一个。输入文件中没有多余的空格。

(x,y)和(X,Y)是窗体的对角。当你创建一个窗体的时候,它自动被“置顶”。你不能用已经存在的标识符来创建窗体,但是你可以删除一个窗体后再用已删除窗体的标识符来创建窗体。坐标用正整数来表示,并且所有的窗体面积都不为 0(x <> X 且 y <> Y)。x 坐标和 y 坐标在 1 —— 32767 的范围内。

输入输出格式

输入格式:

输入文件包含给你的解释程序的一系列命令,每行一个。当输入文件结束时,停止程序。

输出格式:

只对于 s(I) 命令进行输出。当然,输入文件可能有许多 s(I) 命令(不超过500次),所以输出文件应该是一个百分比的序列,每行一个,百分比是窗体可见部分的百分比。百分比应该四舍五入到三位小数。

输入输出样例

输入样例#1:

w(a,10,132,20,12)

w(b,8,76,124,15)

s(a)

输出样例#1:

49.167

说明

题目翻译来自NOCOW。

USACO Training Section 5.3

题解: 这里使用了一种叫做上浮法的算法.

考虑当前要上浮的矩形在第\(k\)层,需要上升到第\(k-1\)层,那么它上面的矩形和它只有两种情况:相交或者不相交,显然不相交的情况可以不用考虑,直接将它提到第\(k-1\)层就可以了.

那么相交的情况怎么处理呢?我们来看一下下面这张图:

图中蓝色的是我们正在上浮的矩形\(B(blue)\),红色的是在\(R(red)\)上面一层挡住\(B\)一部分面积的矩形\(R\),我们可以发现,只要\(R,B\)有交集,那么就可以根据\(R\)的上下左右边将\(B\)分成几个矩形继续上浮(其他的情况可以自己手画一下,因为作图有点麻烦就不再举例子了).

那么根据这个原理,我们就可以将正在上升的矩形分为最多\(4\)部分继续上浮,这一过程可以用\(dfs\)来实现,具体实现看一下代码.

  1. void dfs(int k, int x1, int y1, int x2, int y2){
  2. if(x1 == x2 || y1 == y2) return; // 判断递归的边界条件
  3. if(!k){ ans += (double)(x2-x1)*(y2-y1); return; }
  4. int a1 = a[k].x1, b1 = a[k].y1, a2 = a[k].x2, b2 = a[k].y2;
  5. if(a2 < x1 || a1 > x2 || b2 < y1 || b1 > y2){
  6. dfs(k-1, x1, y1, x2, y2); return; // 无交集直接继续下一层不需要回溯
  7. }
  8. if(a1 <= x1 && b1 <= y1 && x2 <= a2 && y2 <= b2) return; // 已经被某个矩形完全覆盖了那么就不可能被看到了,直接return
  9. dfs(k-1, x1, min(y2, b2), min(x2, a2), y2); // up
  10. dfs(k-1, min(x2, a2), max(y1, b1), x2, y2); // right
  11. dfs(k-1, max(x1, a1), y1, x2, max(y1, b1)); // down
  12. dfs(k-1, x1, y1, max(x1, a1), min(y2, b2)); // left
  13. //这里的四个dfs就是将正在上浮的矩形分割的过程,参数可以自己画几个栗子模拟一下
  14. }

知道了如何统计矩形面积,剩下的只需要模拟一下就好了.

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 100;
  4. // N只有100是因为窗口标识符只有大小写字母和0到9
  5. int used[300], cnt = 0;
  6. double ans = 0, tot = 0;
  7. struct window{
  8. int x1, x2, y1, y2; char c;
  9. window(int _x1 = 0, int _y1 = 0, int _x2 = 0, int _y2 = 0, int _c = 0){
  10. x1 = _x1, y1 = _y1, x2 = _x2, y2 = _y2, c = _c;
  11. }
  12. bool operator == (const window &a) const {
  13. return c == a.c;
  14. }
  15. bool operator < (const window &a) const {
  16. if(x1 != a.x1) return x1 < a.x1;
  17. if(y1 != a.y1) return y1 < a.y1;
  18. if(x2 != a.x2) return x2 < a.x2;
  19. return y2 < a.y2;
  20. }
  21. }a[N], win[300];
  22. void move(window x, int f){
  23. int pos = 0;
  24. for(int i = 1; i <= cnt; i++)
  25. if(a[i] == x){ pos = i; break; }
  26. if(f == 0) for(int i = pos; i >= 2; i--) swap(a[i], a[i-1]);
  27. else for(int i = pos; i < cnt; i++) swap(a[i], a[i+1]);
  28. }
  29. void delet(window x){
  30. int pos;
  31. for(int i = 1; i <= cnt; i++)
  32. if(a[i] == x) pos = i;
  33. used[x.c] = 0, win[x.c] = (window){ 0, 0, 0, 0, 0 };
  34. for(int i = pos+1; i <= cnt; i++) a[i-1] = a[i];
  35. cnt--;
  36. }
  37. void dfs(int k, int x1, int y1, int x2, int y2){
  38. if(x1 == x2 || y1 == y2) return;
  39. if(!k){ ans += (double)(x2-x1)*(y2-y1); return; }
  40. int a1 = a[k].x1, b1 = a[k].y1, a2 = a[k].x2, b2 = a[k].y2;
  41. if(a2 < x1 || a1 > x2 || b2 < y1 || b1 > y2){
  42. dfs(k-1, x1, y1, x2, y2); return;
  43. }
  44. if(a1 <= x1 && b1 <= y1 && x2 <= a2 && y2 <= b2) return;
  45. dfs(k-1, x1, min(y2, b2), min(x2, a2), y2); // up
  46. dfs(k-1, min(x2, a2), max(y1, b1), x2, y2); // right
  47. dfs(k-1, max(x1, a1), y1, x2, max(y1, b1)); // down
  48. dfs(k-1, x1, y1, max(x1, a1), min(y2, b2)); // left
  49. }
  50. int main(){
  51. char opt, id; int x1, y1, x2, y2, pos; window tmp;
  52. while(cin >> opt){
  53. if(opt == 's'){
  54. scanf("(%c)", &id); pos = 0;
  55. for(int i = 1; i <= cnt; i++)
  56. if(a[i] == win[id]) pos = i;
  57. ans = 0, tot = (double)(a[pos].x2-a[pos].x1)*(a[pos].y2-a[pos].y1);
  58. dfs(pos-1, a[pos].x1, a[pos].y1, a[pos].x2, a[pos].y2);
  59. cout << fixed << setprecision(3) << ans*100/tot << endl;
  60. } else {
  61. scanf("(%c,%d,%d,%d,%d)", &id, &x1, &y1, &x2, &y2);
  62. if(x1 > x2) swap(x1, x2); if(y1 > y2) swap(y1, y2);
  63. tmp = (window){ x1, y1, x2, y2, id };
  64. if(opt == 'w'){
  65. if(used[id]) continue;
  66. win[id] = a[++cnt] = tmp, move(tmp, 0);
  67. }
  68. if(opt == 't') move(tmp, 0);
  69. if(opt == 'b') move(tmp, 1);
  70. if(opt == 'd') delet(tmp);
  71. }
  72. opt = getchar();
  73. }
  74. return 0;
  75. }

[洛谷P2745] [USACO5.3]窗体面积Window Area的更多相关文章

  1. luogu【P2745】[USACO5.3]窗体面积Window Area

    这个题 就是个工程题 (然而一开始我并不知道怎么做..还是看nocow的..qwq)(原题入口) 算法为 离散化 + 扫描线  将大坐标变小  并且 用横纵坐标进行扫描 来计算面积 一开始 我想边添加 ...

  2. 洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication【最小割】分析+题解代码

    洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication[最小割]分析+题解代码 题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流. ...

  3. [洛谷P2750] [USACO5.5]贰五语言Two Five

    洛谷题目链接:[USACO5.5]贰五语言Two Five 题目描述 有一种奇怪的语言叫做"贰五语言".它的每个单词都由A-Y这25个字母各一个组成.但是,并不是任何一种排列都是一 ...

  4. [洛谷P1709] [USACO5.5]隐藏口令Hidden Password

    洛谷题目链接:[USACO5.5]隐藏口令Hidden Password 题目描述 有时候程序员有很奇怪的方法来隐藏他们的口令.Binny会选择一个字符串S(由N个小写字母组成,5<=N< ...

  5. [洛谷P2747] [USACO5.4]周游加拿大Canada Tour

    洛谷题目链接:[USACO5.4]周游加拿大Canada Tour 题目描述 你赢得了一场航空公司举办的比赛,奖品是一张加拿大环游机票.旅行在这家航空公司开放的最西边的城市开始,然后一直自西向东旅行, ...

  6. 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

  7. 洛谷1345 [Usaco5.4]奶牛的电信

    题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相 ...

  8. 洛谷 P2746 [USACO5.3]校园网Network of Schools 解题报告

    P2746 [USACO5.3]校园网Network of Schools 题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作"接受学校&q ...

  9. 洛谷——P1345 [USACO5.4]奶牛的电信Telecowmunication

    P1345 [USACO5.4]奶牛的电信Telecowmunication 题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮 ...

随机推荐

  1. 每日scrum--No.1

    Yesterday:无 Today: 查找学校的官方地图和亲自测试其准确性 Problem :不能使地图适应我们的软件;未解决地图上存在的问题: 明天继续加油.

  2. CS小分队第一阶段冲刺站立会议(5月14日)

    昨日成果:为抽号计时器添加了第一类抽号,基本实现界面,功能出现了一些错误 遇到问题:我预想通过timer控件来实现随机抽号而拜托随机生成数,但是出现了只有个位随机滚动,其他位数不动的现象,我预计是数值 ...

  3. 第八次作业(课堂实战)- 项目UML设计

    本次作业博客 团队信息 队名:起床一起肝活队 原组长: 白晨曦(101) 原组员: 李麒 (123) 陈德斌(104) 何裕捷(214) 黄培鑫(217) 王焕仁(233) 林志华(128) 乐忠豪( ...

  4. HDU 5195 DZY Loves Topological Sorting 拓扑排序

    题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5195 bc(中文):http://bestcoder.hdu.edu.cn/contests ...

  5. 领悟JavaScript面向对象

    JavaScript 是面向对象的.但是不少人对这一点理解得并不全面. 在 JavaScript 中,对象分为两种.一种可以称为“普通对象”,就是我们所普遍理解的那些:数字.日期.用户自定义的对象(如 ...

  6. centos 6 编译emacs-24.5

    yum install `yum deplist emacs | grep provider | awk -F: '{print $2}' | awk '{print $1}' | xargs` yu ...

  7. 结对项目之对PIE的测试程序

    项目要求: 构造程序,分别是: 不能触发Fault. 触发Fault,但是不能触发Error. 触发Error,但是不能产生Failure. 结对对象:陈秋月  学号:2013110404  博客地址 ...

  8. 使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证

    使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证   目前WEB 前后端分离的开发模式比较流行,之前做过的几个小项目也都是前后分离的模式,后端使用asp.net weba ...

  9. webgl学习笔记四-动画

    写在前面 建议先阅读下前面我的三篇文章. webgl学习笔记一-绘图单点 webgl学习笔记二-绘图多点 webgl学习笔记三-平移旋转缩放   下面我们将讲解下如何让一个正方形动起来~不断擦除和重绘 ...

  10. get 与 next()