终于打到第二关了,这道题还算简单,属于模拟类型的题,一个重点就是使用深度优先搜索给每个module编号,属于同一个房间的module编号相同,编好号
后其它问题都好办了

/**//*
ID: sdjllyh1
PROG: castle
LANG: JAVA
complete date: 2008/11/27
complexity: O(n * m)
author: LiuYongHui From GuiZhou University Of China
more article: www.cnblogs.com/sdjls
*/
import java.io.*;
import java.util.*;
public class castle

{
private static int m, n;
private static int[][] modules;//存储题目提供的每个“块”的值
private static int creatable = 0;//保存可以去掉一堵墙而得到的最大size
private static int[][] roomsNumber;//保存每个module所属的房间号
private static int roomCount = 0;//记录房间数
private static int[] size;//保存每个房间的大小
private static int removeRow = 0, removeColumn = 0;//removeRow、removeColumn分别表示打破的墙所在行号与列号
private static char removeDerection;//打破墙的方向
public static void main(String[] args) throws IOException
{
init();
run();
output();
System.exit(0);
}
//判断module[row][column]的某个方向时候存在module,注:当这个module在城堡的边缘时返回false
private static boolean hasModule(int row, int column, char direction)
{
boolean retHas = false;
switch (direction)
{
case 'w':
if (column > 0)
{
retHas = true;
}
break;
case 'n':
if (row > 0)
{
retHas = true;
}
break;
case 'e':
if (column < m-1)
{
retHas = true;
}
break;
case 's':
if (row < n-1)
{
retHas = true;
}
break;
default:
retHas = false;
break;
}
return retHas;
}
//根据module值判断某个方向是否有墙
private static boolean hasWall(int moduleValue, int direction)
{
boolean retHas = false;
switch (direction)
{
case 'w':
if ((moduleValue & 1) > 0)
{
retHas = true;
}
break;
case 'n':
if ((moduleValue & 2) > 0)
{
retHas = true;
}
break;
case 'e':
if ((moduleValue & 4) > 0)
{
retHas = true;
}
break;
case 's':
if ((moduleValue & 8) > 0)
{
retHas = true;
}
break;
default:
retHas = false;
break;
}
return retHas;
}
//深度优先搜索,给所有与module[row][column]联通的module们设置同样的房间号
private static void dfs(int row, int column)
{
//如果这个房间的房间号还不知道
if (roomsNumber[row][column] == -1)
{
//给它指定房间号
roomsNumber[row][column] = roomCount;
//下面考虑四个方向的连通性,联通的房间指定相同的房间号roomCount
if (hasModule(row,column,'n') && (!hasWall(modules[row][column],'n')))
{
dfs(row - 1, column);
}
if (hasModule(row, column, 's') && (!hasWall(modules[row][column], 's')))
{
dfs(row + 1, column);
}
if (hasModule(row, column, 'w') && (!hasWall(modules[row][column], 'w')))
{
dfs(row, column - 1);
}
if (hasModule(row, column, 'e') && (!hasWall(modules[row][column], 'e')))
{
dfs(row, column + 1);
}
}
}
private static void run()
{
//使用深度优先搜索计算每个module的房间号
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (roomsNumber[i][j] == -1)
{
dfs(i, j);
roomCount++;
}
}
}
//计算每个房间的大小
size = new int[roomCount];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
size[roomsNumber[i][j]]++;
}
}
//找到一堵墙,使得打破后可以得到最大的房间
//注意,i、j的循环顺序保证了我们打破的是最西南方的墙
for (int j = 0; j < m; j++)
{
for (int i = n-1; i >= 0; i--)
{
//考虑打破北方的墙
//如果北面有房间且有墙
if (hasModule(i, j, 'n') && hasWall(modules[i][j], 'n'))
{
//获得两个房间的编号
int roomNumber1 = roomsNumber[i][j];
int roomNumber2 = roomsNumber[i - 1][j];
//如果不是同一个房间
if (roomNumber1 != roomNumber2)
{
//如果打破这堵墙是最优的
if (creatable < size[roomNumber1] + size[roomNumber2])
{
//更新最优值
creatable = size[roomNumber1] + size[roomNumber2];
removeRow = i;
removeColumn = j;
removeDerection = 'N';
}
}
}
//-------------我是傻傻的分割线----------------
//考虑打破东边的墙,同上
if (hasModule(i, j, 'e') && hasWall(modules[i][j], 'e'))
{
int roomNumber1 = roomsNumber[i][j];
int roomNumber2 = roomsNumber[i][j + 1];
if (roomNumber1 != roomNumber2)
{
if (creatable < size[roomNumber1] + size[roomNumber2])
{
creatable = size[roomNumber1] + size[roomNumber2];
removeRow = i;
removeColumn = j;
removeDerection = 'E';
}
}
}
}
}
}
private static void init() throws IOException
{
BufferedReader f = new BufferedReader(new FileReader("castle.in"));
StringTokenizer st = new StringTokenizer(f.readLine());
m = Integer.parseInt(st.nextToken());
n = Integer.parseInt(st.nextToken());
modules = new int[n][m];
for (int i = 0; i < n; i++)
{
st = new StringTokenizer(f.readLine());
for (int j = 0; j < m; j++)
{
modules[i][j] = Integer.parseInt(st.nextToken());
}
}
f.close();
roomsNumber = new int[n][m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
roomsNumber[i][j] = -1;//-1表示未知
}
}
}
private static void output() throws IOException
{
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("castle.out")));
out.println(roomCount);
int largest = 0;
for (int i = 0; i < roomCount; i++)
{
largest = Math.max(largest, size[i]);
}
out.println(largest);
out.println(creatable);
out.println((removeRow+1) + " " + (removeColumn+1) + " " + removeDerection);
out.close();
}
}
浙公网安备 33010602011771号