• AOJ 0531 坐标离散化


    涂色:(日文题目,自己翻译成了中文)为了宣传信息竞赛,要在长方形的三合板上喷油漆来制作招牌。三合板上不需要涂色的部分预先贴好了护板。被护板隔开的区域要涂上不同的颜色,比如上图就应该涂上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[2 * MAX_N][2 * MAX_N], // 填充遍历用,代表坐标(i, j)处是否空白(压缩后)
     13 dx[4] = { 1, -1, 0, 0 }, dy[4] = { 0, 0, 1, -1 };
     14  
     15 // 压缩坐标,将坐标的值变成“这是第几种值”,返回一共有几种坐标
     16 int compress(int *x1, int *x2, int w)
     17 {
     18     vector<int>xs;
     19  
     20     for (int i = 0; i < N; ++i)
     21     {
     22         int tx1 = x1[i], tx2 = x2[i];
     23         if (1 <= tx1 && tx1 < w) xs.push_back(tx1);
     24         if (1 <= tx2 && tx2 < w) xs.push_back(tx2);
     25     }
     26     xs.push_back(0);
     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 = 0; 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() - 1;
     36 }
     37  
     38 int bfs()
     39 {
     40     int ans = 0;
     41     for (int i = 0; i < H; ++i)
     42     {
     43         for (int j = 0; 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 = 0; i < 4; ++i)
     55                 {
     56                     int tx = nx + dx[i], ty = ny + dy[i];
     57                     if (tx < 0 || W < tx || ty < 0 || H< ty || fld[ty][tx] > 0) continue;
     58                     que.push(make_pair(tx, ty));
     59                     fld[ty][tx] = 1;
     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 = 0; i < N; ++i)
     74         {
     75             cin >> X1[i] >> Y1[i] >> X2[i] >> Y2[i];
     76         }
     77  
     78         memset(fld, 0, sizeof(fld));
     79  
     80         W = compress(X1, X2, W);
     81         H = compress(Y1, Y2, H);
     82  
     83         // imos-法
     84         for (int i = 0; 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 = 0; i < H; i++)
     93         {
     94             for (int j = 1; j < W; j++)
     95             {
     96                 fld[i][j] += fld[i][j - 1];
     97             }
     98         }
     99         // 纵向累积
    100         for (int i = 1; i < H; i++)
    101         {
    102             for (int j = 0; j < W; j++)
    103             {
    104                 fld[i][j] += fld[i - 1][j];
    105             }
    106         }// 累积完后,fld中非0部分表示有挡板
    107         cout << bfs() << endl;
    108     }
    109     return 0;
    110 }
    111 ///////////////////////////End Sub//////////////////////////////////
    View Code
  • 相关阅读:
    Django ajax 实现 loading 效果
    K8S service 简单介绍
    K8S Pod 生命周期 (二)
    异度之刃 Xenoblade 后感
    Nested Prefab Mode 嵌套预制体 保存问题 Dirty
    GIT速成
    Surface电池阈值
    如何删除通知栏无效图标(重置任务栏通知区域)
    Mouse For Winpad
    Re:LieF ~親愛なるあなたへ~ 后感
  • 原文地址:https://www.cnblogs.com/bestefforts/p/8987538.html
Copyright © 2020-2023  润新知