题目

题目描述

有一个城堡,城堡中有若干个房间,房间与房间之间用墙来进行分隔。现在我们需要统计这个城堡有多少个房间,并且还要找出最大的房间的面积是多少(一个单元格就代表一个单元面积)。城堡的主人现在想要在这些房间中通过打通一面墙来使两个房间合并,并且要求合并之后的房间是所有可能情况中最大的房间。我们需要计算的是,合并之后最大的房间是多大,需要打通的墙壁是哪一面。我们进行房间改造有一定的规则:从城堡的左下角开始往右上角遍历单元格,每个单元格只要考虑两面墙(如果有相应的墙壁),优先考虑朝向为北的墙壁(N),之后再考虑朝向为东的墙壁(E)。

问题输入

输入与平常有些不同,我们是每个单元格中有一个数字x。现在我们有如下规定:

  • 1:代表朝向为西的墙壁
  • 2:代表朝向为北的墙壁
  • 4:代表朝向为东的墙壁
  • 8:代表朝向为南的墙壁

    如果x可以由1,2,4,8这几个数中的某些数字相加得到,那就代表这个位置有相应的墙壁。城堡最大为50*50的单元格组成。

问题输出

输出房间改造之前的房间数、最大的房间面积。然后输出房间改造之后的最大的房间面积、需要改造的墙壁。

样例输入

7 4
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13

样例输出

5
9
16
4 1 E

解题思路

既然是要按照一定的规则输出最优的方案,我们肯定是需要遍历所有可能的情况。所以我最一开始就直接用宽搜找到所有的房间,并且统计每个房间的大小。之后我再枚举每一面墙壁,在枚举墙壁的时候思维比较混乱,因为之前统计房间我没有对房间进行编号,并且没有保存每个房间的面积。所以在枚举墙壁的时候我又用洪泛式的搜索来计算去掉这面墙壁之后可以增加多大的面积。最后的结果当然是超时啦......

所以后来看了下别人的思路提示,才想起来应该在统计房间大小的时候顺便对房间进行编号,而且还要对房间的大小进行记录,便于之后枚举墙壁的时候直接可以获得这些信息。

在解题的过程中我们可以发现墙壁的方向是1,2,4,8,这是2的幂次方,所以我们可以用位运算的技巧来判断每个单元格的墙壁情况。这是一个解题技巧,可以让程序变得更加优雅。

解题代码

/*
ID: yinzong2
PROG: castle
LANG: C++11
*/
#define MARK
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 55; int M, N;
// castle存地图,roomId用来保存每个点所属的房间编号
int castle[maxn][maxn], roomId[maxn][maxn];
map<int, int> roomSize; // 房间号映射到房间大小
int maxSize1, maxSize2; int dirX[4] = {0, -1, 0, 1};
int dirY[4] = {-1, 0, 1, 0}; struct Room {
int x,y;
int value;
}; void findRoom(int x, int y, int roomNum) {
int rSize = 0;
queue<Room> Q;
while (!Q.empty())Q.pop();
Room r;
r.x = x; r.y = y; r.value = castle[x][y];
Q.push(r);
roomId[x][y] = roomNum;
rSize++;
while (!Q.empty()) {
Room r1, r2;
r1 = Q.front(); Q.pop();
for (int i = 0; i < 4; ++i) {
int dir = 1 << i;
if (0 == (dir&r1.value)) {
int tx = r1.x + dirX[i];
int ty = r1.y + dirY[i];
if (tx >= 1 && tx <= N && ty >= 1 && ty <= M && 0 == roomId[tx][ty]) {
roomId[tx][ty] = roomNum;
r2.x = tx;
r2.y = ty;
r2.value = castle[tx][ty];
rSize++;
Q.push(r2);
}
}
}
}
maxSize1 = max(maxSize1, rSize);
roomSize[roomNum] = rSize;
} int main() {
#ifdef MARK
freopen("castle.in", "r", stdin);
freopen("castle.out", "w", stdout);
#endif // MARK
while (cin >> M >> N) {
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= M; ++j) {
cin >> castle[i][j];
roomId[i][j] = 0;
}
}
maxSize1 = 0;
int roomNum = 1;
roomSize.clear();
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= M; ++j) {
if (0 == roomId[i][j]) {
findRoom(i, j, roomNum);
roomNum++;
}
}
}
cout << roomNum-1 << endl << maxSize1 << endl;
// 枚举所有的墙壁,房间从左下往右上方向,墙壁优先选择N,其次为E
maxSize2 = 0;
int wallX, wallY;
char wallDir;
for (int y = 1; y <= M; ++y) {
for (int x = N; x >= 1; --x) {
int value = castle[x][y];
// N 方向
if ((value & 2) != 0) {
int tx = x + dirX[1];
int ty = y + dirY[1];
if (tx >= 1 && tx <= N && ty >= 1 && ty <= M && roomId[x][y] != roomId[tx][ty]) {
int totSize = roomSize[ roomId[x][y] ] + roomSize[ roomId[tx][ty] ];
if (totSize > maxSize2) {
maxSize2 = totSize;
wallX = x;
wallY = y;
wallDir = 'N';
}
}
}
// E 方向
if ((value & 4) != 0) {
int tx = x + dirX[2];
int ty = y + dirY[2];
if (tx >= 1 && tx <= N && ty >= 1 && ty <= M && roomId[x][y] != roomId[tx][ty]) {
int totSize = roomSize[ roomId[x][y] ] + roomSize[ roomId[tx][ty] ];
if (totSize > maxSize2) {
maxSize2 = totSize;
wallX = x;
wallY = y;
wallDir = 'E';
}
}
}
}
}
cout << maxSize2 << endl;
cout << wallX << " " << wallY << " " << wallDir << endl;
}
return 0;
}

USACO Section 2.1 The Castle 解题报告的更多相关文章

  1. USACO Section 1.3 Prime Cryptarithm 解题报告

    题目 题目描述 牛式的定义,我们首先需要看下面这个算式结构: * * * x * * ------- * * * <-- partial product 1 * * * <-- parti ...

  2. USACO Section 1.4 Arithmetic Progressions 解题报告

    题目 题目描述 现在给你一个数集,里面的数字都是由p^2+q^2这种形式构成的0 <= p,q <= M,我现在需要你在其中找出一个长为N的等差数列,数列中的第一个数字为a,公差为b,当你 ...

  3. USACO Section 1.3 Combination Lock 解题报告

    题目 题目描述 农夫John的牛从农场逃脱出去了,所以他决定用一个密码锁来把农场的门锁起来,这个密码锁有三个表盘,每个表盘都是环形的,而且上面刻有1~N,现在John设了一个开锁密码,而且这个锁的设计 ...

  4. USACO Section 1.3 Barn Repair 解题报告

    题目 题目描述 某农夫有一个养牛场,所有的牛圈都相邻的排成一排(共有S个牛圈),每个牛圈里面最多只圈养一头牛.有一天狂风卷积着乌云,电闪雷鸣,把牛圈的门给刮走了.幸运的是,有些牛因为放假,所以没在自己 ...

  5. USACO Section 1.3 Mixing Milk 解题报告

    题目 题目描述 Merry Milk Makers 公司的业务是销售牛奶.它从农夫那里收购N单位的牛奶,然后销售出去.现在有M个农夫,每个农夫都存有一定量的牛奶,而且每个农夫都会有自己的定价.假设所有 ...

  6. USACO Section 1.2 Dual Palindromes 解题报告

    题目 题目描述 有一些数(如 21),在十进制时不是回文数,但在其它进制(如二进制时为 10101)时就是回文数. 编一个程序,从文件读入两个十进制数N.S.然后找出前 N 个满足大于 S 且在两种以 ...

  7. USACO Section 1.2 Palindromic Squares 解题报告

    题目 题目描述 输入一个基数B,现在要从1到300之间找出一些符合要求的数字N.如果N的平方转换成B进制数之后是一个回文串,那么N就符合要求.我们将N转换成B进制数输出,然后再将N的平方转换成B进制数 ...

  8. USACO Section 1.2 Milking Cows 解题报告

    题目 题目描述 有3个农夫每天早上五点钟便起床去挤牛奶,现在第一个农夫挤牛奶的时刻为300(五点钟之后的第300个分钟开始),1000的时候结束.第二个农夫从700开始,1200结束.最后一个农夫从1 ...

  9. USACO Section 1.1 Broken Necklace 解题报告

    题目 题目描述 有一串项链,它是由红蓝白三种颜色的珠子组成的,b代表蓝色,w代表白色,r代表红色,当它完整的时候是一个闭合的环形.现在它在某一个节点断裂了,之前的环形也随之变成了直线形.从两端开始收集 ...

随机推荐

  1. SAP调用RestfulApi接口接收数据

    因为准备要做一个关于调用外部接口的需求,所以自己先练习一下. 程序说明:我已经在.net开发的系统里提供一个api接口,现在在sap访问这个接口,来接收数据. 这里涉及Restful Api知识,以后 ...

  2. jQuery调用Asp.Net后台方法

    常用的ajax就不讲了,这里主要是说通过ajax调用asp.net后台的cs文件暴露的方法. 前台: <%@ Page Language="C#" AutoEventWire ...

  3. 欧几里得算法(及扩展)&&快速幂(二分+位运算)

    最近在二中苦逼地上课,天天听数论(当然听不懂) 但是,简单的还是懂一点的 1.欧几里得算法 说得这么高级干什么,gcd入门一个月的人都会吧,还需要BB? 证明可参照其他博客(不会),主要就是gcd(a ...

  4. mfc 嵌套类

    嵌套类 一. 嵌套类 嵌套类的定义 将某个类的定义放在另一个类的内部,这样的类定义,叫嵌套类. class AAA { int aaa; class BBB { int bbb; //其它成员或者函数 ...

  5. 用C++实现一个Brainfuck解释器

    Brainfuck是一种极小化的计算机语言,只含有8种运算符,由于fuck在英语中是脏话,这种语言有时被称为brainfck或brainf**,甚至被简称为BF.正如它的名字所暗示,brainfuck ...

  6. gulp.src()内部实现探究

    写在前面 本来是想写个如何编写gulp插件的科普文的,突然探究欲又发作了,于是就有了这篇东西...翻了下源码看了下gulp.src()的实现,不禁由衷感慨:肿么这么复杂... 进入正题 首先我们看下g ...

  7. Linux使用expect实现免手动密码输入,linux免密码登陆

    使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明,初学者一般都是照抄.收藏.可是为什么要这么写却不知其然.本文用一个最短的例子说明脚本的原理.  脚本代码如下:  ###### ...

  8. 再探Redux Middleware

    前言 在初步了解Redux中间件演变过程之后,继续研究Redux如何将中间件结合.上次将中间件与redux硬结合在一起确实有些难看,现在就一起看看Redux如何加持中间件. 中间件执行过程 希望借助图 ...

  9. 开源一个最近写的spring与mongodb结合的demo(spring-mongodb-demo)

    由于工作需要,给同事们分享了一下mongodb的使用,其中主要就是做了一个spring-data+mongodb的小例子,本着分享的精神,就上传到了github.com上,有需要的同学请移步githu ...

  10. Sprint计划会议内容

    项目名称:蹭课神器 会议内容 首先我们讨论了项目的工作量及实施流程 一.工作认领 二.界面的总体规划 三.主要功能的设计 四.设计数据库 五.编写项目报告 六.软件测试和推广 然后我们进行了工作认领, ...