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

这个题 就是个工程题然而一开始我并不知道怎么做。。还是看nocow的。。qwq)(原题入口

算法为 离散化 + 扫描线  将大坐标变小  并且 用横纵坐标进行扫描 来计算面积

一开始 我想边添加 点的坐标 边 离散  后来发现 有点问题 

因为 它离散后的坐标 并不是按顺序来排(因为后来可能还加入中间的点 就需要重新离散)

所以 我就把一开始的操作 和 坐标先存下来 进行离散 再进行操作 (QAQ 搞了好久

后面 就是计算面积了 把一个大矩形 划分成 许多个小矩形 再进行标记 来计算面积了

代码:

  1 #include <cstdio> 
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <cctype>
  7 #include <iostream>
  8 #include <map>
  9 #include <vector>
 10 #define For(i, l, r) for(int i = (l); i <= (int)(r); ++i)
 11 #define Fordown(i, r, l) for(int i = (r); i >= (int)(l); --i)
 12 #define Set(a, v) memset(a, v, sizeof(a)) 
 13 #define pb push_back
 14 using namespace std;
 15 
 16 inline int read(){
 17   int x = 0, fh = 1; char ch;
 18   for(; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
 19   for(; isdigit(ch); ch = getchar()) x = (x<<1) + (x<<3) + (ch^'0');
 20   return x * fh;
 21 }
 22 
 23 const int N = 2550;
 24 map <int, int> fx, fy; //map数组 记录这个坐标是否被离散化过 
 25 int gx[1<<15], gy[1<<15]; //反向存储标号对应的坐标 
 26 int cnt_x = 0, cnt_y = 0, cnt = 0; //离散化的个数 
 27 char id[N]; //记录id数组 
 28 
 29 int now_deep = 2*(1<<15), top_deep = (1<<15), back_deep = 3*(1<<15);
 30 struct node {
 31     int xl, yl, xr, yr;
 32     int deep;  //层次 
 33     bool flag; //是否被删除 
 34 }; 
 35 node win[N]; //存储窗户 
 36 
 37 int idx(char ch) {
 38     For (i, 1, cnt) 
 39         if (id[i] == ch) return i;
 40     id[++cnt] = ch;
 41     return cnt;
 42 } //计算当前l的id 
 43 
 44 bool exist[N/2][N/2];
 45 double sum(int num) {
 46     if (!win[num].flag) return 0.0000; //如果已经删除 就返回0.0 (好像并没有用) 
 47     Set(exist, false); //判断小矩形是否存在 
 48     int sum_area = 0;
 49     int now_area = 0;
 50 
 51     For (i, win[num].xl, win[num].xr-1)
 52         For (j, win[num].yl, win[num].yr-1)
 53         {   exist[i][j] = true; //一开始置为真 
 54             sum_area += fabs ((gx[i+1] - gx[i] ) * (gy[j+1] - gy[j]) ) ; } //计算本来的总面积 
 55 
 56     For (i, 1, cnt) 
 57         if (win[i].flag && win[i].deep < win[num].deep) //如果在它上面 并且 未被删除 
 58             For (j, win[i].xl, win[i].xr-1)
 59                 For (k, win[i].yl, win[i].yr-1) 
 60                     exist[j][k] = false; //小矩形置为假 
 61     
 62     For (i, win[num].xl, win[num].xr-1)
 63         For (j, win[num].yl, win[num].yr-1)
 64             if (exist[i][j])  //存在 就加上
 65                 now_area += fabs( (gx[i] - gx[i+1]) * (gy[j] - gy[j+1]) ); //计算面积 
 66                 
 67     return ((double)now_area / (double)sum_area * 100.0000); //计算百分比 
 68 }
 69 
 70 struct oper {
 71     char opt;
 72     int l, xl, yl, xr, yr;
 73 };
 74 
 75 oper kk[N]; //存储操作 
 76 int cnt_op = 0;
 77 vector <int> tx; //存储坐标 
 78 vector <int> ty;
 79 
 80 int main(){
 81     freopen ("window.in", "r", stdin);
 82     freopen ("window.out", "w", stdout);
 83     char opt;
 84     while (scanf ("%c", &opt) != EOF) {
 85         char l; 
 86         int xl1, yl1, xr1, yr1;
 87         if (opt == 'w') { 
 88             scanf ("(%c,%d,%d,%d,%d)", &l, &xl1, &yl1, &xr1, &yr1);
 89             if (xl1 > xr1) swap(xl1, xr1);
 90             if (yl1 > yr1) swap(yl1, yr1); //左下角 和 右上角 
 91             kk[++cnt_op] = (oper) {opt, l, xl1, yl1, xr1, yr1};
 92             tx.pb (xl1); tx.pb(xr1); ty.pb(yl1); ty.pb(yr1);
 93         }
 94         else {
 95             scanf ("(%c)", &l);
 96             kk[++cnt_op] = (oper) {opt, l, 0, 0, 0, 0};
 97         }
 98     }
 99 
100     sort (tx.begin(), tx.end() );
101     For (i, 0, tx.size() - 1) 
102         if (!fx[tx[i]] ) {fx[tx[i]] = ++cnt_x; gx[cnt_x] = tx[i]; }
103     sort (ty.begin(), ty.end() );
104     For (i, 0, ty.size() - 1)
105         if (!fy[ty[i]] ) {fy[ty[i]] = ++cnt_y; gy[cnt_y] = ty[i]; }
106     //运用map的离散化 可能有点慢 
107 
108     For (i, 1, cnt_op) {
109         //cout << "id:  " << i << endl;
110         opt = kk[i].opt;
111         char l = kk[i].l; int num;
112         int xl1 = kk[i].xl, yl1 = kk[i].yl, xr1 = kk[i].xr, yr1 = kk[i].yr;
113         if (opt == 'w') {
114             num = idx(l);
115             win[num].xl = fx[xl1]; win[num].xr = fx[xr1];
116             win[num].yl = fy[yl1]; win[num].yr = fy[yr1];
117             win[num].flag = true; win[num].deep = --top_deep; //放在最上面 并将flag为真 
118         } //创建一个新窗体(window)
119         else if (opt == 't') {
120             num = idx(l);
121             win[num].deep = --top_deep;
122         }//将窗体置顶(top)
123         else if (opt == 'b') {
124             num = idx(l);
125             win[num].deep = ++back_deep;
126         }//将窗体置底(back)
127         else if (opt == 'd') {
128             num = idx(l);
129             win[num].flag = false;
130         //    cout << num << endl;
131         }//删除一个窗体(delete)
132         else if (opt == 's') {
133             num = idx(l);
134             printf ("%.3lf\n", sum(num));
135         }//输出窗体可见部分的百分比(sum)
136     }
137 }

 

posted @ 2017-07-10 10:30  zjp_shadow  阅读(370)  评论(0编辑  收藏  举报