涂颜料

  题目大意:在一个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容易爆栈,当然你用栈来模拟我没话说)。

 #include <iostream>
#include <algorithm>
#include <functional>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <queue>
#define MAX_N 1010 using namespace std; static int X1[], Y1[], X2[], Y2[], fld[MAX_N * ][MAX_N * ],
dx[] = { -, , , }, dy[] = { , -, , }; static int compress(int *const, int *const, const int, const int);
static int bfs(const int, const int);
void imos(const int, const int, const int); int main(void)
{
int W, H, N; //freopen("D:\\input.txt", "r", stdin);
while ()
{
scanf("%d%d", &W, &H);
if (W == && H == )
break;
scanf("%d", &N);
for (int i = ; i < N; i++)
{
scanf("%d%d%d%d", &X1[i], &Y1[i], &X2[i], &Y2[i]);
}
W = compress(X1, X2, W, N);
H = compress(Y1, Y2, H, N); imos(W, H, N);
cout << bfs(W, H) << endl;
}
return EXIT_SUCCESS;
} static int compress(int *const s1, int *const s2, const int W, const int N)
{
//坐标离散化
vector<int>xs; for (int i = ; i < N; i++)
{
if ( < s1[i] && s1[i] < W) xs.push_back(s1[i]);
if ( < s2[i] && s2[i] < W) xs.push_back(s2[i]);
}
xs.push_back();
xs.push_back(W);//加上边界条件
sort(xs.begin(), xs.end());
xs.erase(unique(xs.begin(), xs.end()), xs.end()); for (int i = ; i < N; i++)
{
s1[i] = find(xs.begin(), xs.end(), s1[i]) - xs.begin();
s2[i] = find(xs.begin(), xs.end(), s2[i]) - xs.begin();
}
return xs.size() - ;//注意这里要获取的边界条件使得size加了2,要减1才能刚好变成真正的数组长度
} static int bfs(const int W, const int H)
{
int ans = ;
for (int i = ; i < W; i++)
for (int j = ; j < H; j++)
{
if (fld[i][j])continue;//搜索没有挡板的位置
ans++; queue<pair<int, int> > que;
que.push(make_pair(i, j));
while (!que.empty())
{
int tx = que.front().first, ty = que.front().second;
que.pop();
for (int i = ; i < ; i++)
{
int ttx = tx + dx[i], tty = ty + dy[i];
if ( <= ttx && ttx <= W
&& <= tty && tty <= H
&& !fld[ttx][tty])
{
que.push(make_pair(ttx, tty));
fld[ttx][tty] = ;
}
}
}
}
return ans;
} void imos(const int W, const int H, const int N)
{
//imos法统计区间
memset(fld, , sizeof(fld)); for (int i = ; i < N; i++)//统计影响力
{
fld[X1[i]][Y1[i]]++;
fld[X1[i]][Y2[i]]--;
fld[X2[i]][Y1[i]]--;
fld[X2[i]][Y2[i]]++;
}
for (int i = ; i < W; i++)//累计横向
for (int j = ; j < H; j++)
fld[i][j] += fld[i][j - ]; for (int j = ; j < H; j++)//累计纵向
for (int i = ; i < W; i++)
fld[i][j] += fld[i - ][j];
//非零部分就是有挡板的位置了
}

  

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

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

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

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

    [题目链接] http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0531 [题目大意] 给出一张图,和一些矩形障碍物,求该图没被障碍物覆 ...

  2. Aizu - 0531 Paint Color

    白书例题,直接用书上的暴力压缩坐标是可以的,但是看了别人的博客的写法,大概是理解了思想但是看不懂为什么那么压缩,先放这,等明白了补上 #define debug #include<stdio.h ...

  3. Aizu 0531 "Paint Color" (坐标离散化+DFS or BFS)

    传送门 题目描述: 为了宣传信息竞赛,要在长方形的三合板上喷油漆来制作招牌. 三合板上不需要涂色的部分预先贴好了护板. 被护板隔开的区域要涂上不同的颜色,比如上图就应该涂上5种颜色. 请编写一个程序计 ...

  4. AOJ 0531 坐标离散化

    涂色:(日文题目,自己翻译成了中文)为了宣传信息竞赛,要在长方形的三合板上喷油漆来制作招牌.三合板上不需要涂色的部分预先贴好了护板.被护板隔开的区域要涂上不同的颜色,比如上图就应该涂上5种颜色. 请编 ...

  5. Android Paint画笔及Color .

    引自:http://blog.csdn.net/q445697127/article/details/7736926 Paint paint = new Paint(); // 设置paint为无锯齿 ...

  6. LC 265. Paint House II

    There are a row of n houses, each house can be painted with one of the k colors. The cost of paintin ...

  7. ProgrammingContestChallengeBook

    POJ 1852 Ants POJ 2386 Lake Counting POJ 1979 Red and Black AOJ 0118 Property Distribution AOJ 0333 ...

  8. imos-累积和法

    在解AOJ 0531 Paint Color时,学到了一个累积和的妙用--imos法,由于原文是日语,所以特意翻译过来.值得一提的是,作者Kentaro Imajo跟鄙人同龄,却已取得如此多的成就,而 ...

  9. JAVAFX纯手写布局

    主页面效果: 第一栏的效果: 工程目录: package MessageBean; /** * * @author novo */ public class Message { private Str ...

随机推荐

  1. Linux服务器管理: 系统管理:系统资源查看

    vmstat 命令: 查看或监控系统资源 [root@localhostA1 ~]# vmstat procs -----------memory---------- ---swap-- -----i ...

  2. Highcharts X轴名称太长,如何设置下面这种样式

      Highcharts所有的图表除了饼图都有X轴和Y轴,默认情况下,x轴显示在图表的底部,y轴显示在左侧(多个y轴时可以是显示在左右两侧),通过chart.inverted = true 可以让x, ...

  3. 常见的几个angular.js的问题

    来源于网络收集 一.ng-show/ng-hide 与 ng-if的区别? 我们都知道ng-show/ng-hide实际上是通过display来进行隐藏和显示的.而ng-if实际上控制dom节点的增删 ...

  4. Hadoop 之Mong DB 之CentOS 6 使用 yum 安装MongoDB及服务器端配置

    安装MongoDB的方法有很多种,可以源代码安装,在Centos也可以用yum源安装的方法.由于MongoDB更新得比较快,我比较喜欢用yum源安装的方法.64位Centos下的安装步骤如下: 1.准 ...

  5. 【python网络编程】新浪爬虫:关键词搜索爬取微博数据

    上学期参加了一个大数据比赛,需要抓取大量数据,于是我从新浪微博下手,本来准备使用新浪的API的,无奈新浪并没有开放关键字搜索的API,所以只能用爬虫来获取了.幸运的是,新浪提供了一个高级搜索功能,为我 ...

  6. linux 脚本命令匹配并获取下一行数据

    三种方式: 匹配“Title”并打印出匹配行的下一行 grep  -A 1 'Title'  urfile awk '/Title/{getline a;print $0"\n"a ...

  7. C#获取文件/字节数组MD5值方法

    找了很多,就这个管用,有时间好好研究一番 public static string GetMD5Hash(string fileName) { try { FileStream file = new ...

  8. sqlserver2008清日志

    use [DB Name] Select NAME,size From sys.database_files GO ALTER DATABASE [DB Name] SET RECOVERY SIMP ...

  9. 4 个最好的 Linux 引导程序

    导读 当你打开你的机器,开机自检(POST)成功完成后,BIOS(基本输入输出系统)立即定位所配置的引导介质,并从 MBR(主引导记录)或 GUID(全局唯一标识符)分区表读取一些命令,这是引导介质的 ...

  10. delay() .split()

    delay(500) 延时多少秒后执行,结合animate()使用 delay(500).animate({},时间) .split() stringObject.split(separator,ho ...