N(1 ≤ N ≤ 1,000)个不同颜色的不透明矩形被摆放在了一个白色的宽A高B(1 ≤ A,B ≤ 10,000)的网格上,矩形的边与网格的边平行。所有的长方形都放置在网格内,所以我们会看到不同形状的各种颜色。
坐标系统的原点(0,0)设在这张白纸的左下角,而坐标轴则平行于网格边缘。求最后能看到的颜色,以及各颜色所占面积。
输入:
第1 行包含三个整数A、B 和N,由空格分开。
第2 到N+1 行,每行五个整数:llx, lly, urx, ury, color,分别表示一个长方形的左下角坐标,右上角坐标和颜色。颜色1 和底部白纸的颜色相同(1 ≤ color ≤2,500)。矩形在输入文件中出现的顺序即为放置的先后顺序。
这道题用到的方法叫做漂浮法。
想象一下,矩形倒序从水底一个一个地浮上来,如果遇到上面有东西的部分就停住,没有被挡住的地方继续上浮...
如何实现?
用一个变量记录当前浮到第几层,找到它上面第一个有交集的,分成四部分继续递归。
分成四部分的时候,每查完一个要改一下当前边界。
核心代码:
(F = Floor,C = Ceil)
int dfs(int L,int R,int F,int C,int k) { while(k <= n && (L >= r[k].x2 || R <= r[k].x1 || F >= r[k].y2 || C <= r[k].y1)) k++; if(k > n) return (R-L)*(C-F); int sum = 0; if(L < r[k].x1) sum += dfs(L,r[k].x1,F,C,k+1), L = r[k].x1; if(R > r[k].x2) sum += dfs(r[k].x2,R,F,C,k+1), R = r[k].x2; if(F < r[k].y1) sum += dfs(L,R,F,r[k].y1,k+1), F = r[k].y1; if(C > r[k].y2) sum += dfs(L,R,r[k].y2,C,k+1), C = r[k].y2; return sum; }
代码如下
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #define MogeKo qwq using namespace std; const int maxn = 2505; int a,b,n,ans[maxn]; struct rec { int x1,x2,y1,y2,col; } r[maxn]; int dfs(int L,int R,int F,int C,int k) { while(k <= n && (L >= r[k].x2 || R <= r[k].x1 || F >= r[k].y2 || C <= r[k].y1)) k++; if(k > n) return (R-L)*(C-F); int sum = 0; if(L < r[k].x1) sum += dfs(L,r[k].x1,F,C,k+1), L = r[k].x1; if(R > r[k].x2) sum += dfs(r[k].x2,R,F,C,k+1), R = r[k].x2; if(F < r[k].y1) sum += dfs(L,R,F,r[k].y1,k+1), F = r[k].y1; if(C > r[k].y2) sum += dfs(L,R,r[k].y2,C,k+1), C = r[k].y2; return sum; } int main() { scanf("%d%d%d",&a,&b,&n); for(int i = 1; i <= n; i++) scanf("%d%d%d%d%d",&r[i].x1,&r[i].y1,&r[i].x2,&r[i].y2,&r[i].col); ans[1] = a*b; for(int i = n; i >= 1; i--) { int s = dfs(r[i].x1,r[i].x2,r[i].y1,r[i].y2,i+1); ans[r[i].col] += s; ans[1] -= s; } for(int i = 1; i <= maxn; i++) if(ans[i]) printf("%d %d ",i,ans[i]); return 0; }