洛谷P1457 城堡 The Castle

题目:https://www.luogu.org/problemnew/show/1457

题目描述

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

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

城堡的平面图被划分成M*N(1 <=M,N<=50)个正方形的单位,一个这样的单位可以有0到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个房间,而且一定有一面墙可以被移走。

输入输出格式

输入格式:

 

第一行有两个整数: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

 

解析

哇好刺激的大爆搜(~ ̄▽ ̄)~

不过这波爆搜由于代码量较大错误点不断orz-_-!

我想到的方法是并查集(因为前阵子刚练过)( ﹁ ﹁ ) ~→

关于前两问,大爆搜啊(~ ̄▽ ̄)~

一般学过搜索的人都会做,顺便枚举出每一个块内的节点数。

ok,前两问搞定(~ ̄▽ ̄)~

后两问就是一个枚举问题啦,枚举每个点的每条边,更新最大值和位置,搞定。

但,你确定你做对了吗(⊙ω⊙)

有坑点的哦Σ( ° △ °|||)︴

①本题东西优先,然后南北优先,应该先枚举列数,再枚举行数Σ( ° △ °|||)︴

②有一些墙就被一个连通块包住了,此时的面积应就为本块的面积Σ( ° △ °|||)︴

吐槽一下无良出题人和自己的读题水平orz。

好了代码如下:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 using namespace std;
  7 #define maxn 55
  8 int n,m,re,sz;
  9 int get_pos[maxn][maxn],tot;
 10 int pos_geth[maxn*maxn],pos_getl[maxn*maxn]; 
 11 int fa[maxn*maxn];
 12 bool wall[maxn*maxn][4];
 13 int ans_tot,ans_size;
 14 bool has[maxn*maxn];
 15 int num[maxn*maxn];
 16 bool vis[maxn*maxn];
 17 int max_csize;
 18 int cpos,cface;
 19 /*
 20 0 west
 21 1 north
 22 2 east
 23 3 south
 24 */
 25 int finda(int x){
 26     if (fa[x]==x) return fa[x];
 27     else return fa[x]=finda(fa[x]);
 28 }
 29 void unionn(int x,int y){
 30     int fx=finda(x),fy=finda(y);
 31     if (fx==fy) return;
 32     fa[fy]=fx;
 33 }
 34 void dfs(int x,int fm){
 35     vis[x]=true;
 36     if (!wall[x][0]&&fm!=x-1&&!vis[x-1]){
 37         ++sz;
 38         unionn(x,x-1);
 39         dfs(x-1,x);
 40     }
 41     if (!wall[x][1]&&fm!=x-m&&!vis[x-m]){
 42         ++sz;
 43         unionn(x,x-m);
 44         dfs(x-m,x);
 45     }
 46     if (!wall[x][2]&&fm!=x+1&&!vis[x+1]){
 47         ++sz;
 48         unionn(x,x+1);
 49         dfs(x+1,x);
 50     }
 51     if (!wall[x][3]&&fm!=x+m&&!vis[x+m]){
 52         ++sz;
 53         unionn(x,x+m);
 54         dfs(x+m,x);
 55     }
 56 }
 57 int main(){
 58     scanf("%d%d",&m,&n);
 59     for (int i=1;i<=n;++i){
 60         for (int j=1;j<=m;++j){
 61             get_pos[i][j]=++tot;
 62             pos_getl[tot]=j;
 63             pos_geth[tot]=i;
 64             fa[tot]=tot;
 65             scanf("%d",&re);
 66             if (re&1) wall[tot][0]=true;
 67             if (re&2) wall[tot][1]=true;
 68             if (re&4) wall[tot][2]=true;
 69             if (re&8) wall[tot][3]=true;
 70         }
 71     } 
 72     for (int i=1;i<=tot;++i){
 73         if (fa[i]==i){
 74             has[i]=true;
 75             sz=1;
 76             dfs(i,-1);
 77             num[i]=sz;
 78             ans_size=max(ans_size,sz);
 79             ++ans_tot;
 80         }
 81     }
 82     printf("%d\n%d\n",ans_tot,ans_size);
 83     for (int j=1;j<=m;++j){
 84         for (int i=n;i>=1;--i){
 85             if (wall[get_pos[i][j]][1]&&i!=1){
 86                 if (finda(get_pos[i][j])==finda(get_pos[i-1][j])){
 87                     continue;
 88                 }
 89                 if (num[finda(get_pos[i][j])]+num[finda(get_pos[i-1][j])]>max_csize){
 90                     max_csize=num[finda(get_pos[i][j])]+num[finda(get_pos[i-1][j])];
 91                     cpos=get_pos[i][j]; cface=1;
 92                 }
 93             }
 94             if (wall[get_pos[i][j]][2]&&j!=m){
 95                 if (finda(get_pos[i][j])==finda(get_pos[i][j+1])){
 96                     continue;
 97                 }
 98                 if (num[finda(get_pos[i][j])]+num[finda(get_pos[i][j+1])]>max_csize){
 99                     max_csize=num[finda(get_pos[i][j])]+num[finda(get_pos[i][j+1])];
100                     cpos=get_pos[i][j]; cface=2;
101                 }
102             }
103         }
104     }
105     if (ans_size>=max_csize){
106         printf("%d\n",ans_size);
107         for (int j=1;j<=m;++j){
108             for (int i=n;i>=1;--i){
109                 if (wall[get_pos[i][j]][1]&&i!=1){
110                     printf("%d %d N",i,j);    
111                     return 0;        
112                 }
113                 if (wall[get_pos[i][j]][2]&&j!=m){
114                     printf("%d %d E",i,j);
115                     return 0;
116                 }
117             }
118         }
119     }else{
120         printf("%d\n",max_csize);
121         printf("%d %d ",pos_geth[cpos],pos_getl[cpos]);
122         if (cface==1) printf("N");
123         if (cface==2) printf("E");
124     }
125     return 0;
126 }
View Code

 

posted @ 2017-11-07 22:06  lonlyn  阅读(156)  评论(0编辑  收藏  举报