Greedy:Paint Color(AOJ 0531)

涂颜料

  题目大意:在一个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文件,这个好评

时间: 2024-10-12 11:55:37

Greedy:Paint Color(AOJ 0531)的相关文章

Android中自定义常用的三个对象解析(Paint,Color,Canvas)

Paint,Color,Canvas Paint:画笔对象,画图用的"笔" Color:颜色,相当于调料 Canvas:画布,现实中的纸板 Paint 画笔 常用的方法就是设置和获取到画笔的样式: paint.setStyle(); 设置画笔的风格,空心的或者是实心的 paint.setColor(); 设置画笔的颜色 paint.setStrokeWidth(); 设置边框线的宽度 paint.setAlpha(); 设置画笔的Alpha值 paint.setAntiAlias();

AOJ 0531:Paint Color(二维离散+imos)

[题目链接] http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0531 [题目大意] 给出一张图,和一些矩形障碍物,求该图没被障碍物覆盖的部分被划分为几个连通块 [题解] 首先对图中的点进行离散化,对于一个障碍物来说, 我们将其看做左闭右开上闭下开的图形,所以在离散的时候只要离散障碍物的点即可. 之后我们利用imos积累法得出哪些部分是障碍物,就可以统计连通块了. [代码] #include <cstdio> #include

Android Paint画笔及Color .

引自:http://blog.csdn.net/q445697127/article/details/7736926 Paint paint = new Paint(); // 设置paint为无锯齿 paint.setAntiAlias(true); // 设置颜色 paint.setColor(Color.RED); // 设置颜色 paint.setColor(Color.rgb(255, 0, 0)); // 设置透明度 paint.setAlpha(256); // 提取颜色 Colo

防手机联系人功能的实现

package com.loaderman.contactsrecycledemo; /* * This code is cloned from DefaultItemAnimator provided by support library v7-recyclerView * * Copyright (C) 2014 The Android Open Source Project * Copyright (c) 2014-2015 Gabriele Mariotti. * * Licensed

JavaFX Application应用实例

下面代码演示的是JavaFX进程命令行参数的实例.大家可以参阅一下. /*原文地址:http://www.manongjc.com/article/134.html */ import java.util.List; import javafx.application.Application; import javafx.geometry.Insets; import javafx.scene.Group; import javafx.scene.Scene; import javafx.sce

等价类划分方法及其示例(2)

package threebox; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.layo

SpannableString 你应该知道的那些效果显示

一个人需要隐藏多少秘密才能巧妙地度过一生 - 仓央嘉措 前言 上次看到一款学习的 App,有这样一个功能,在一个 TextView 中有一段英文,点击英文单词通过语音朗读出来.语音先不考虑,怎么去实现 TextView 点击获取每个单词的内容的呢? 肯定是用SpannableString去实现的呗,不然你今天讲它干嘛.嘿嘿,我说的对不对? 答案是肯定的,由于惯性我们先来看看效果图: 我这里没有获取每个单词,而是获取的每段句子.效果图上也展示了一些其他的SpannableString效果,大多数可

冯斌:JavaFx实例(十三)“FontEffect”

本实例演示用JavaFx改变文字的字体,制造文字的阴影和倒影等效果.将会用到如下的三个类: javafx.scene.text.Font javafx.scene.effect.DropShadow javafx.scene.effect.Reflection 本实例的代码如下: import javafx.application.Application; import javafx.scene.layout.Pane;  import javafx.scene.Scene;  import j

冯斌:JavaFx实例(九)“Text”

在JavaFx中Text类定义了一个node,这个node能显示字符串,如下图所示. 其中点(x,y)是字符串的起点.Text对象通常放在一个pane对象里.Pane对象的左上角坐标是(0,0),右下角的坐标是(pane.getWidth(),pane.getHeight()).多行字符串用\n分割开来. Text类的UML图如下图所示.一个shape就是一个node,Shape类是其他所有图形类的根类. 程序实例清单如下: import javafx.application.Applicati