IOI'94 - Day 1
In a stroke of luck almost beyond imagination, Farmer John wassent a ticket to the Irish Sweepstakes (really a lottery) for hisbirthday. This ticket turned out to have only the winning numberfor the lottery! Farmer John won a fabulous castle in the Irishcountryside.
Bragging rights being what they are in Wisconsin, Farmer Johnwished to tell his cows all about the castle. He wanted to knowhow many rooms it has and how big the largest room was. In fact,he wants to take out a single wall to make an even bigger room.
Your task is to help Farmer John know the exact room count andsizes.
The castle floorplan is divided into M (wide) by N (1 <=M,N<=50)square modules. Each such module can have between zero and fourwalls. Castles always have walls on their "outer edges" to keepout the wind and rain.
Consider this annotated floorplan of a castle:
1 2 3 4 5 6 7 ############################# 1 # | # | # | | # #####---#####---#---#####---# 2 # # | # # # # # #---#####---#####---#####---# 3 # | | # # # # # #---#########---#####---#---# 4 # -># | | | | # # ############################# # = Wall -,| = No wall -> = Points to the wall to remove to make the largest possible new room
By way of example, this castle sits on a 7 x 4 base. A "room" includesany set of connected "squares" in the floor plan. This floorplan containsfive rooms (whose sizes are 9, 7, 3, 1, and 8 in no particular order).
Removing the wall marked by the arrow merges a pair of rooms tomake the largest possible room that can be made by removing a singlewall.
The castle always has at least two rooms and always has a wallthat can be removed.
PROGRAM NAME: castle
INPUT FORMAT
The map is stored in the form of numbers, one number for each module,M numbers on each of N lines to describe the floorplan. The inputorder corresponds to the numbering in the example diagram above.
Each module number tells how many of the four walls exist andis the sum of up to four integers:
- 1: wall to the west
- 2: wall to the north
- 4: wall to the east
- 8: wall to the south
Inner walls are defined twice; a wall to the south in module 1,1is also indicated as a wall to the north in module 2,1.
Line 1: | Two space-separated integers: M and N |
Line 2..: | M x N integers, several per line. |
SAMPLE INPUT (file castle.in)
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
OUTPUT FORMAT
The output contains several lines:
Line 1: | The number of rooms the castle has. |
Line 2: | The size of the largest room |
Line 3: | The size of the largest room creatable by removing one wall |
Line 4: | The single wall to remove to make thelargest room possible |
Choose the optimal wall to remove from the set of optimal wallsby choosing the module farthest to the west (and then, if stilltied, farthest to the south). If still tied, choose 'N' before 'E'.Name that wall by naming the module that borders it on either thewest or south, along with a direction of N or E giving the locationof the wall with respect to the module.
SAMPLE OUTPUT (file castle.out)
5 9 16 4 1 E
/*
ID: wxx54331
PROG: castle
LANG: C++
*/
/*
首先使用floodFill算法得出这个图的所有连通块
之后再按题目要求枚举可以拆掉的墙对房间的大小进行扩充,找到最大的扩充方案
*/
#include<iostream>
#include<fstream>
using namespace std;
const int MAX = 50;
int row, column; //整个图的大小
int wall[MAX][MAX][5]; //0->west, 1->north, 2->east, 3->south, 4->group
bool visited[MAX][MAX]; //记录某个单元格是否已经被访问过
int dx[] = {-1, 0, 1, 0}; /*按←↑→↓的顺序移动*/
int dy[] = {0, -1, 0, 1};
int group; //记录房间数
int roomSize[MAX*MAX]; //记录每个房间的大小
int maxSize;
int r, c; //记录要拆除的墙所在的单元格的行和列位置
char dir; //记录要拆除的墙的方位
void readData();
void floodFill(int x, int y);
void merge(int x, int y);
int main()
{
ofstream fout("castle.out");
readData();
/*floodFill算法找出房间的数量以及大小*/
for(int i = 0; i < row; ++i)
for(int j = 0; j < column; ++j)
if(!visited[i][j])
{
roomSize[group] = 0;
floodFill(i, j);
group++;
}
fout << group << endl;
for(int i = 0; i < group; ++i)
maxSize = max(maxSize, roomSize[i]);
fout << maxSize << endl;
/*从最西南边的墙开始枚举,拆除后面积是否为最大
西边优先级最高,南边优先级次之,N墙优先级>E墙*/
maxSize = 0;
for(int i = 0; i < column; ++i)
for(int j = row-1; j >= 0; --j)
merge(j,i);
fout << maxSize << endl;
fout << r << " " << c << " " << dir << endl;
fout.close();
return 0;
}
void readData()
{
ifstream fin("castle.in");
int number;
fin >> column >> row;
for(int i = 0; i < row; ++i)
for(int j = 0; j < column; ++j)
{
fin >> number;
/*思考的时候将数字想为二进制,比如6是0110,每次从右边取出一位*/
for(int k = 0; k <= 3; ++k)
{
wall[i][j][k] = number % 2;
number = number >> 1;
}
wall[i][j][4] = 0;
}
fin.close();
}
void floodFill(int y, int x) /*按照坐标轴来考虑*/
{
visited[y][x] = true;
wall[y][x][4] = group;
roomSize[group]++;
for(int i = 0; i <= 3; ++i) //遍历4堵墙
{
int nx = x + dx[i]; //向上下左右的房间移动
int ny = y + dy[i];
if(nx < 0 || ny < 0 || nx >= column || ny >= row) //越界
continue;
if(visited[ny][nx] || wall[y][x][i]) //新的房间已经访问过,或者现在要移动到的方向有墙
continue;
floodFill(ny, nx);
}
}
void merge(int y, int x)
{
int sum = 0;
if(y>=1 && wall[y][x][4]!=wall[y-1][x][4]) //拆除N边的墙
{
sum = roomSize[wall[y][x][4]] + roomSize[wall[y-1][x][4]];
if(sum > maxSize)
{
maxSize = sum;
r = y+1;
c = x+1;
dir = 'N';
}
}
if(x<column-1 && wall[y][x][4]!=wall[y][x+1][4]) //拆除E边的墙
{
sum = roomSize[wall[y][x][4]] + roomSize[wall[y][x+1][4]];
if(sum > maxSize)
{
maxSize = sum;
r = y+1;
c = x+1;
dir = 'E';
}
}
}