题干:

Thanks to a certain "green" resources company, there is a new profitable industry of oil skimming. There are large slicks of crude oil floating in the Gulf of Mexico just waiting to be scooped up by enterprising oil barons. One such oil baron has a special plane that can skim the surface of the water collecting oil on the water's surface. However, each scoop covers a 10m by 20m rectangle (going either east/west or north/south). It also requires that the rectangle be completely covered in oil, otherwise the product is contaminated by pure ocean water and thus unprofitable! Given a map of an oil slick, the oil baron would like you to compute the maximum number of scoops that may be extracted. The map is an NxN grid where each cell represents a 10m square of water, and each cell is marked as either being covered in oil or pure water.

Input

The input starts with an integer K (1 <= K <= 100) indicating the number of cases. Each case starts with an integer N (1 <= N <= 600) indicating the size of the square grid. Each of the following N lines contains N characters that represent the cells of a row in the grid. A character of '#' represents an oily cell, and a character of '.' represents a pure water cell.

Output

For each case, one line should be produced, formatted exactly as follows: "Case X: M" where X is the case number (starting from 1) and M is the maximum number of scoops of oil that may be extracted.

Sample Input

1
6
......
.##...
.##...
....#.
....##
......

Sample Output

Case 1: 3

题目大意:

有一个地图,' . '代表水,' # ' 代表油。每个单元格是10*10的,现用一个'.'或'#'表示,现有10*20的勺子可以提取出水上漂浮的油,问最多可以提取几勺的油; 每次提取的时候勺子放的位置都要是油,不然就被海水污染而没有价值了。

一句话题意:每次恰好覆盖相邻的两个#,不能重复,求最大覆盖次数。

解题报告:

建模:用模板每次恰好覆盖相邻的两个#,同一个点不能重复覆盖,求最大覆盖次数。

建图:这题有两种建图方式。一种是奇偶建图,即(i+j)的奇偶数来建图,vis1表示左侧集合,vis2表示右侧。因为木板能且仅能只能放在(i+j)%2==0 和 (i+j)%2==1这两个相邻的位置上,所以我们这么去分集合。然后找匹配就可以了。

第二种建图方式就是如果是'#'那就++cnt,就是都用同一套体系来给‘#’标号,这样最后匈牙利搞完之后答案/2即可。

下面分别给出代码。

建图方式1的AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,ans;
int vis1[605][605],vis2[605][605],line[605][605];
bool used[605*605];
char maze[605][605];
int tot1,tot2;
int nxt[605*605];
bool find(int x) {for(int i = 1; i<=tot2; i++) {if(line[x][i] && !used[i]) {used[i]=1;if(nxt[i] == 0 || find(nxt[i])) {nxt[i] = x;return 1;}}}return 0 ;
}
int match() {int sum = 0;memset(nxt,0,sizeof nxt);for(int i = 1; i<=tot1; i++) {memset(used,0,sizeof used);if(find(i)) sum++;}return sum;
}
int main()
{int iCase = 0,t=0;scanf("%d",&t);while(t--) {tot1 = tot2 = 0;scanf("%d",&n);memset(vis1,0,sizeof vis1);memset(vis2,0,sizeof vis2);memset(line,0,sizeof line);for(int i = 1; i<=n; i++) {scanf("%s",maze[i]+1);}for(int i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) {if(maze[i][j] == '#') {if((i+j)&1) vis2[i][j] = ++tot2;else vis1[i][j] = ++tot1;}}}for(int i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) {if((i+j)&1) continue;if(maze[i][j] == '#') {if(maze[i][j+1] == '#' && j+1 <= n) line[vis1[i][j]][vis2[i][j+1]]=1;if(maze[i][j-1] == '#' && j-1 >= 1) line[vis1[i][j]][vis2[i][j-1]]=1;if(maze[i+1][j] == '#' && i+1 <= n) line[vis1[i][j]][vis2[i+1][j]]=1;if(maze[i-1][j] == '#' && i-1 >= 1) line[vis1[i][j]][vis2[i-1][j]]=1;}}}printf("Case %d: %d\n",++iCase,match());}return 0 ;
}

建图方式2的AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,ans;
int vis[605][605],line[605][605];
bool used[605*605];
char maze[605][605];
int tot;
int nxt[605*605];
bool find(int x) {for(int i = 1; i<=tot; i++) {if(line[x][i] && !used[i]) {used[i]=1;if(nxt[i] == 0 || find(nxt[i])) {nxt[i] = x;return 1;}}}return 0 ;
}
int match() {int sum = 0;memset(nxt,0,sizeof nxt);for(int i = 1; i<=tot; i++) {memset(used,0,sizeof used);if(find(i)) sum++;}return sum;
}
int main()
{int iCase = 0,t=0;scanf("%d",&t);while(t--) {
//      tot1 = tot2 = 0;tot=0;scanf("%d",&n);memset(vis,0,sizeof vis);memset(line,0,sizeof line);for(int i = 1; i<=n; i++) {scanf("%s",maze[i]+1);}for(int i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) {if(maze[i][j] == '#') {vis[i][j] = ++tot;}}}for(int i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) {if(maze[i][j] == '#') {if(maze[i][j+1] == '#' && j+1 <= n) line[vis[i][j]][vis[i][j+1]]=1;if(maze[i][j-1] == '#' && j-1 >= 1) line[vis[i][j]][vis[i][j-1]]=1;if(maze[i+1][j] == '#' && i+1 <= n) line[vis[i][j]][vis[i+1][j]]=1;if(maze[i-1][j] == '#' && i-1 >= 1) line[vis[i][j]][vis[i-1][j]]=1;}}}printf("Case %d: %d\n",++iCase,match()/2);}return 0 ;
}

总结:

再好好想想建图!和POJ - 2226这个最小点覆盖的题比较一下,也是写过博客的。这俩题还是有共同之处的。

【HDU - 4185】Oil Skimming (二分图,建图,匈牙利算法)相关推荐

  1. HDU 2063 过山车 (二分图匹配之匈牙利算法)

    过山车 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  2. 数据结构与算法学习笔记15:最大流问题 / 二分图 / 有权无权二分图的匹配 / 匈牙利算法 / 银行家算法 / 稳定婚配

    数据结构与算法学习笔记15:最大流问题 / 二分图 / 有权无权二分图的匹配 / 匈牙利算法 / 银行家算法 / 稳定婚配 引入小题:最短路径 最大流问题(maximum flow problem) ...

  3. 【HDU - 1281 】棋盘游戏 (经典的二分图匹配,匈牙利算法,枚举删除顶点,必须边,关建边)

    题干: 小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的"车",并且使得他们不能互相攻击,这当然很简单,但是Gardon限制了只有某些格子才 ...

  4. 【HDU - 5090】Game with Pearls (匈牙利算法,二分图匹配)

    题干: Tom and Jerry are playing a game with tubes and pearls. The rule of the game is: 1) Tom and Jerr ...

  5. Leapin' Lizards HDU - 2732 (恶心的建图。。)

    这道题其实不难...就是建图恶心了点....emm... 题意: 多源多汇 + 拆边 青蛙跳柱子, 每根柱子都有一定的承载能力, 青蛙跳上去之后柱子的承载能力就会减一,跳到边界就能活 跳不到就over ...

  6. 二分图的最大匹配 匈牙利算法

    基本概念 1.二分图: 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别 ...

  7. 二分图匹配之匈牙利算法

    二分图的基本概念: 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于 ...

  8. 二分图的最大匹配—匈牙利算法

    [基本概念]: 二分图: 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分 ...

  9. python最长匹配_二分图最大匹配:匈牙利算法的python实现

    二分图匹配是很常见的算法问题,一般用匈牙利算法解决二分图最大匹配问题,但是目前网上绝大多数都是C/C++实现版本,没有python版本,于是就用python实现了一下深度优先的匈牙利算法,本文使用的是 ...

  10. HDU 2063:过山车(匈牙利算法模板题)

    过山车 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

最新文章

  1. 最新视觉Transformer综述(2017-2020年)
  2. 英国工会联盟报告:机器人技术和AI让三分之一的人失业
  3. 百度商业大规模微服务分布式监控系统-凤睛
  4. 社招转行CV算法的心酸之路:越朴素的方法,往往越容易成功!
  5. c:forEach 取 map的值
  6. 全国大型水库水情数据汇总2018
  7. Java面向对象第二章课后习题
  8. Java 8:一文掌握 Lambda 表达式 | CSDN 博文精选
  9. 物理综合:Compile
  10. Silverlight+WCF 新手实例 象棋 WCF通讯基础(十四)
  11. IPM是如何控制三相电机的
  12. OPPO A59m怎么刷机 OPPO A59m的刷机教程 OPPO A59m完美解除账号锁
  13. 安装VidCutter,这是Linux Ubuntu的视频切割器
  14. 三方支付之支付宝支付实现逻辑
  15. 国夜景最美丽的十大城市
  16. 开始做一个简单的记账工具
  17. 台式计算机常用哪些主板结构,一种台式计算机用主板的制作方法
  18. 单相逆变电路实战!(基于STM32F103C8T6的单相逆变电路,PID控制输出额定电压)
  19. java 定时启动window程序、自动滑动鼠标
  20. Mybatis-Plus如何使用分页

热门文章

  1. N元语法模型的数据稀疏问题解决方法之一:Good-Turing平滑
  2. 第三章 随机变量的数字特征
  3. 第一章 概率论的基本概念
  4. [Leedcode][JAVA]第[945]题
  5. codeup 1128: 出租车费 贪心|找规律
  6. cocos 禁掉快速点击_win10系统快速运行debug程序的技巧
  7. vue——走马灯-类轮播图
  8. jquery查找ul属性不是hide,jQuery的ul显示/隐藏功能
  9. 甘肃政法学院计算机科学与技术试题,甘肃政法学院计算机科学与技术专业课程教学大纲.doc...
  10. 画王八java代码参数_java画乌龟源代码-郭遥航.doc