欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

P1457 城堡 The Castle

程序员文章站 2022-06-11 09:32:27
...
P1457 城堡 The Castle

题目描述

我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张“幸运爱尔兰”(一种**)。结果这张**让他获得了这次比赛唯一的奖品——坐落于爱尔兰郊外的一座梦幻般的城堡!

喜欢吹嘘的农夫约翰立刻回到有着吹嘘传统的威斯康辛老家开始吹嘘了, 农夫约翰想要告诉他的奶牛们关于他城堡的一切。他需要做一些吹嘘前的准备工作:比如说知道城堡有多少个房间,每个房间有多大。另外,农夫约翰想要把一面单独的墙(指两个单位间的墙)拆掉以形成一个更大的房间。 你的工作就是帮农夫约翰做以上的准备,算出房间数与房间的大小。

城堡的平面图被划分成M*N(1 <=M,N<=50)个正方形的单位,一个这样的单位可以有0到4面墙环绕。城堡周围一定有外墙环绕以遮风挡雨。(就是说平面图的四周一定是墙。)

请仔细研究下面这个有注解的城堡平面图:

P1457 城堡 The Castle

友情提示,这个城堡的平面图是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个房间,而且一定有一面墙可以被移走。

输入输出格式

输入格式:

 

第一行有两个整数:M和N 城堡的平面图用一个由数字组成的矩阵表示,一个数字表示一个单位,矩阵有N行M列。输入与样例的图一致。

每一个单位的数字告诉我们这个单位的东西南北是否有墙存在。每个数字是由以下四个整数的某个或某几个或一个都没有加起来的。

1: 在西面有墙

2: 在北面有墙

4: 在东面有墙

8: 在南面有墙

城堡内部的墙会被规定两次。比如说(1,1)南面的墙,亦会被标记为(2,1)北面的墙。

 

输出格式:

 

输出包含如下4行:

第 1 行: 城堡的房间数目。

第 2 行: 最大的房间的大小

第 3 行: 移除一面墙能得到的最大的房间的大小

第 4 行: 移除哪面墙可以得到面积最大的新房间。

选择最佳的墙来推倒。有多解时选最靠西的,仍然有多解时选最靠南的。同一格子北边的墙比东边的墙更优先。

用该墙的南邻单位的北墙或西邻单位的东墙来表示这面墙,方法是输出邻近单位的行数、列数和墙的方位("N"(北)或者"E"(东))。

 

输入输出样例

输入样例#1:
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
输出样例#1:
5
9
16
4 1 E

说明

USACO 2.1

翻译来自NOCOW

 

这个题不难 不知道大家对处理墙有没有好方法

我在这里介绍一个

题目说墙的号码是 1 2 4 8

这四个数显然都是2的n次幂

这里有一个性质 就是 1 2 4 8四个数可以组成1-15之内的任意一个数

且每个数只有一种组成方式

15就是1+2+4+8

14就是2+4+8

13就是1+4+8

12就是4+8

。。。。。

所以 每一个数字 代表了唯一的一种情况

我们就可以 判断了

输出墙  按照如下顺序遍历 只找北墙和东墙 

P1457 城堡 The Castle

 

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>

const int MAXN=600;
const int MAXM=4000;

int n,m,id,ans,mx;

int f[MAXN][MAXN],sum[MAXM],d[MAXM][4],belong[MAXM];

bool vis[MAXN][MAXN];

int x[4]={0,1,0,-1};
int y[4]={1,0,-1,0};

struct node {
	int to;
	int next;
};

inline void read(int&x) {
	register char c=getchar();
	for(x=0;!isdigit(c);c=getchar());
	for(;isdigit(c);x=x*10+c-48,c=getchar());
}

inline int max(int a,int b) {return a<b?b:a;}

inline void cal(int now,int p) {
	if(p>=8) d[now][1]=1,p-=8;else d[now][1]=0;
	if(p>=4) d[now][0]=1,p-=4;else d[now][0]=0;
	if(p>=2) d[now][3]=1,p-=2;else d[now][3]=0;
	if(p>=1) d[now][2]=1,p-=1;else d[now][2]=0;
}

void DFS(int the_x,int the_y) {
	int now=(the_x-1)*m+the_y;
	cal(now,f[the_x][the_y]);
	vis[the_x][the_y]=true;
	belong[now]=id;
	++sum[id];
	mx=max(sum[id],mx);
	for(int i=0;i<4;++i) {
		int next_x=the_x+x[i];
		int next_y=the_y+y[i];
		if(next_x<1||next_y<1||next_x>n||next_y>m) continue;
		if(vis[next_x][next_y]||d[now][i]) continue;
		DFS(next_x,next_y);
	}
}

int hh() {
	read(m);read(n);
	for(int i=1;i<=n;++i) 
	  for(int j=1;j<=m;++j)
	    read(f[i][j]);
	for(int i=1;i<=n;++i)
	  for(int j=1;j<=m;++j) 
	  	if(!vis[i][j]) ++id,DFS(i,j);
	printf("%d\n%d\n",id,mx);
	ans=-1;char p;
	int b_x,b_y;
	for(int j=1;j<=m;++j)
	 for(int i=n;i>=1;--i)  {
	 	if(d[(i-1)*m+j][3]&&i!=1) {
			if(belong[(i-1)*m+j]!=belong[(i-2)*m+j])
			  if(sum[belong[(i-1)*m+j]]+sum[belong[(i-2)*m+j]]>ans) 
			    b_x=i,b_y=j,ans=sum[belong[(i-1)*m+j]]+sum[belong[(i-2)*m+j]],p='N';
		}
	 	if(d[(i-1)*m+j][0]&&j!=m) {
	  		if(belong[(i-1)*m+j]!=belong[(i-1)*m+j+1])
	  		  if(sum[belong[(i-1)*m+j]]+sum[belong[(i-1)*m+j+1]]>ans)
	  		    b_x=i,b_y=j,ans=sum[belong[(i-1)*m+j]]+sum[belong[(i-1)*m+j+1]],p='E';
		}
	  }
	printf("%d\n%d %d %c\n",ans,b_x,b_y,p);
	return 0;
} 

int sb=hh();
int main(int argc,char**argv){;}