• Greedy:Paint Color(AOJ 0531)


    IMG_4037

    涂颜料

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

      这一题是书上的作业题,书上有一道差不多的例题,但是书上那道例题是用的直线的,而且他的坐标是点格,而这道题是坐标(这个很重要,我一开始没有区分好导致理解不了)。那么这一题肯定要用到坐标压缩的(1000000*1000000太大了,我们可以把木板压缩到最小就可以了),标准的直接看代码就好了,很容易理解。)

      然后现在这题很难的一个地方在于,怎么高效地判断和填充木板区域,当然我们可以一个一个木板找,然后匹配填充,但是显然这样比较慢(这种操作复杂度是0(W*H*N),虽然坐标压缩了以后这个不会很大,但是还是有其他更好的方法的),这里有一个很神奇的imos法,imos法不仅仅是用来做这种ACM的题的,还是一个很实用的工程算法。

      imos法详解(中文版,我暂时还没得到原作者的同意,所以直接丢博主的链接好了)  

    http://www.hankcs.com/program/algorithm/imos_method.html

      imos法详解(日文原版,这里有上面中文版没有的imos如何应对特殊的三角形矩阵的填充和一些函数(二次函数,高斯函数)的问题)   

    http://imoz.jp/algorithms/imos_method.html

      (ps:上面两个的那个影响力计算的图是错的(代码没有错),-1的位置错了。)

      最后我们用BFS就可以了(DFS容易爆栈,当然你用栈来模拟我没话说)。

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <functional>
      4 #include <string.h>
      5 #include <stdio.h>
      6 #include <vector>
      7 #include <queue>
      8 #define MAX_N 1010
      9 
     10 using namespace std;
     11 
     12 static int X1[1010], Y1[1010], X2[1010], Y2[1010], fld[MAX_N * 2][MAX_N * 2], 
     13             dx[4] = { -1, 0, 0, 1 }, dy[4] = { 0, -1, 1, 0 };
     14 
     15 static int compress(int *const, int *const, const int, const int);
     16 static int bfs(const int, const int);
     17 void imos(const int, const int, const int);
     18 
     19 int main(void)
     20 {
     21     int W, H, N;
     22 
     23     //freopen("D:\input.txt", "r", stdin);
     24     while (1)
     25     {
     26         scanf("%d%d", &W, &H);
     27         if (W == 0 && H == 0)
     28             break;
     29         scanf("%d", &N);
     30         for (int i = 0; i < N; i++)
     31         {
     32             scanf("%d%d%d%d", &X1[i], &Y1[i], &X2[i], &Y2[i]);
     33         }
     34         W = compress(X1, X2, W, N);
     35         H = compress(Y1, Y2, H, N);
     36 
     37         imos(W, H, N);
     38         cout << bfs(W, H) << endl;
     39     }
     40     return EXIT_SUCCESS;
     41 }
     42 
     43 static int compress(int *const s1, int *const s2, const int W, const int N)
     44 {
     45     //坐标离散化
     46     vector<int>xs;
     47 
     48     for (int i = 0; i < N; i++)
     49     {
     50         if (0 < s1[i] && s1[i] < W) xs.push_back(s1[i]);
     51         if (0 < s2[i] && s2[i] < W) xs.push_back(s2[i]);
     52     }
     53     xs.push_back(0);
     54     xs.push_back(W);//加上边界条件
     55     sort(xs.begin(), xs.end());
     56     xs.erase(unique(xs.begin(), xs.end()), xs.end());
     57 
     58     for (int i = 0; i < N; i++)
     59     {
     60         s1[i] = find(xs.begin(), xs.end(), s1[i]) - xs.begin();
     61         s2[i] = find(xs.begin(), xs.end(), s2[i]) - xs.begin();
     62     }
     63     return xs.size() - 1;//注意这里要获取的边界条件使得size加了2,要减1才能刚好变成真正的数组长度
     64 }
     65 
     66 static int bfs(const int W, const int H)
     67 {
     68     int ans = 0;
     69     for (int i = 0; i < W; i++)
     70         for (int j = 0; j < H; j++)
     71         {
     72             if (fld[i][j])continue;//搜索没有挡板的位置
     73             ans++;
     74 
     75             queue<pair<int, int> > que;
     76             que.push(make_pair(i, j));
     77             while (!que.empty())
     78             {
     79                 int tx = que.front().first, ty = que.front().second;
     80                 que.pop();
     81                 for (int i = 0; i < 4; i++)
     82                 {
     83                     int ttx = tx + dx[i], tty = ty + dy[i];
     84                     if (0 <= ttx && ttx <= W
     85                         && 0 <= tty && tty <= H
     86                         && !fld[ttx][tty])
     87                     {
     88                         que.push(make_pair(ttx, tty));
     89                         fld[ttx][tty] = 1;
     90                     }
     91                 }
     92             }
     93         }
     94     return ans;
     95 }
     96 
     97 void imos(const int W, const int H, const int N)
     98 {
     99     //imos法统计区间
    100     memset(fld, 0, sizeof(fld));
    101 
    102     for (int i = 0; i < N; i++)//统计影响力
    103     {
    104         fld[X1[i]][Y1[i]]++;
    105         fld[X1[i]][Y2[i]]--;
    106         fld[X2[i]][Y1[i]]--;
    107         fld[X2[i]][Y2[i]]++;
    108     }
    109     for (int i = 0; i < W; i++)//累计横向
    110         for (int j = 1; j < H; j++)
    111             fld[i][j] += fld[i][j - 1];
    112 
    113     for (int j = 0; j < H; j++)//累计纵向
    114         for (int i = 1; i < W; i++)
    115             fld[i][j] += fld[i - 1][j];
    116     //非零部分就是有挡板的位置了
    117 }

      

      另外吐槽一下AOJ,编译器是个什么鬼编译器,连queue<pair<int,int>>都要报错,居然不能识别pair<int,int>和queue的>的区分,不过AOJ有input和output文件,这个好评

      参考:http://www.hankcs.com/program/algorithm/aoj-0531-paint-color.html

  • 相关阅读:
    HDU 1717 小数化分数2(最大公约数)
    C#计数器
    C#计数器
    c#计算器
    c#计算器
    PHP 错误与异常 笔记与总结(18 )页面重定向实现
    想使用 MongoDB ,你应该了解这8个方面!
    大数据代表未来,投资力度增强
    统计学和数据挖掘的异同探讨
    统计学和数据挖掘的异同探讨
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/5195984.html
Copyright © 2020-2023  润新知