The Castle

http://train.usaco.org/usacoprob2?a=oWzBIFCNDmw&S=castle


==描述==

我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张“幸运爱尔兰”(一种彩票)。结果这张彩票让他获得了这次比赛唯一的奖品——坐落于爱尔兰郊外的一座梦幻般的城堡!喜欢吹嘘的农夫约翰立刻回到有着吹嘘传统的威斯康辛老家开始吹嘘了, 农夫约翰想要告诉他的奶牛们关于他城堡的一切。他需要做一些吹嘘前的准备工作:比如说知道城堡有多少个房间,每个房间有多大。另外,农夫约翰想要把一面单独的墙(指两个单位间的墙)拆掉以形成一个更大的房间。你的工作就是帮农夫约翰做以上的准备,算出房间数与房间的大小。 城堡的平面图被划分成M*N(1 <=M,N<=50)个正方形的单位,一个这样的单位可以有0到4面墙环绕。城堡周围一定有外墙环绕以遮风挡雨。(就是说平面图的四周一定是墙。)请仔细研究下面这个有注解的城堡平面图:

     1   2   3   4   5   6   7
   #############################
 1 #   |   #   |   #   |   |   #
   #####---#####---#---#####---#   
 2 #   #   |   #   #   #   #   #
   #---#####---#####---#####---#
 3 #   |   |   #   #   #   #   #   
   #---#########---#####---#---#
 4 # ->#   |   |   |   |   #   #   
   ############################# 


 # =墙壁    -,| = 没有墙壁
 -> =指向一面墙,这面墙推掉的话我们就有一间最大的新房间

友情提示,这个城堡的平面图是7×4个单位的。一个“房间”的是平面图中一个由“#”、“-”、“|”围成的格子(就是图里面的那一个个的格子)。比如说这个样例就有5个房间。(大小分别为9、7、3、1、8个单位(排名不分先后)) 移去箭头所指的那面墙,可以使2个房间合为一个新房间,且比移去其他墙所形成的房间都大。(原文为:Removing the wall marked by the arrow merges a pair of rooms to make the largest possible room that can be made by removing a single wall. )城堡保证至少有2个房间,而且一定有一面墙可以被移走。

#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
using namespace std;
int n, m;
struct room
{
	int wall[4];	//0---西	1---北		2---东		3---南
	int g;
} a[55][55];
int f[2501];
void dfs(int x, int y, int z)		//x->行 y->列 
{
	if(a[x][y].g) return;
	f[z]++;
	a[x][y].g = z;
	if(!a[x][y].wall[0]) dfs(x, y - 1, z);
	if(!a[x][y].wall[1]) dfs(x - 1, y, z);
	if(!a[x][y].wall[2]) dfs(x, y + 1, z);
	if(!a[x][y].wall[3]) dfs(x + 1, y, z);
}
int main()
{
	ifstream fin("castle.in");
	ofstream fout("castle.out");
	int t, maxt = 0, maxi, maxj, maxn = 0;
	char maxw;
	fin >> m >> n;
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			fin >> t;
			a[i][j].g = 0;
			for(int k = 0; k < 4; k++) a[i][j].wall[k] = t&(1 << k);
		}
	}
	t = 1;
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			if(a[i][j].g == 0)
			{
				dfs(i, j, t);
				if(maxt < f[t]) maxt = f[t];
				t++;
			}
		}
	}
	fout << t - 1 << endl;
	fout << maxt << endl;
	for(int j = m; j >= 1; j--)
	{
		for(int i = 1; i <= n; i++)
		{
			if(j < m && a[i][j].g != a[i][j + 1].g && f[a[i][j].g] + f[a[i][j + 1].g] >= maxn)
			{
				maxi = i;
				maxj = j;
				maxw = 'E';
				maxn =  f[a[i][j].g] + f[a[i][j + 1].g];
			}
			if(i > 1 && a[i][j].g != a[i - 1][j].g && f[a[i][j].g] + f[a[i - 1][j].g] >= maxn)
			{
				maxi = i;
				maxj = j;
				maxw = 'N';
				maxn = f[a[i][j].g] + f[a[i - 1][j].g];
			}
		}
	}
	fout << maxn << endl;
	fout << maxi << " " << maxj << " " << maxw << endl;
	fout.close();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值