比赛 |
二进制状态表示之搜索中的应用 |
评测结果 |
AAAAAAAA |
题目名称 |
城堡 |
最终得分 |
100 |
用户昵称 |
┭┮﹏┭┮ |
运行时间 |
0.050 s |
代码语言 |
C++ |
内存使用 |
0.72 MiB |
提交时间 |
2023-07-26 17:20:00 |
显示代码纯文本
#include <bits/stdc++.h>
using namespace std;
int xx[10],yy[10];//向各个方向的下x,y变化值
int n,m,ans,s,ss,xx1,yy1,u;
char aa;//ans ss u xx1 yy1 aa按顺序输出
//分别为房间数,最大房间面积,去掉其中一块墙的最大房间面积 , 墙的方位
int v[110][110];//房间和墙位置数组
bool w[110][110];//种子填充dfs bool数组
void init(){
xx[1] = 0,xx[2] = -1,xx[4] = 0,xx[8] = 1;//1西 2北 4东 8南
yy[1] = -1,yy[2] = 0,yy[4] = 1,yy[8] = 0;//向各个方向的下x,y变化值
scanf("%d%d",&m,&n);
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
int x;
scanf("%d",&x);//输入
v[2*i][2*j] = 1;//房间为1,墙为2,多余的四个角为3
while(x){
int z = x & (-x);
v[2*i+xx[z]][2*j+yy[z]] = 2;
x &= (x-1);//墙
}
v[2*i-1][2*j-1] = 3;v[2*i+1][2*j-1] = 3;v[2*i-1][2*j+1] = 3;v[2*i+1][2*j+1] = 3;
//多余的四个角
}
}
}
void dfs(int x,int y){
if(v[x][y] == 2 || v[x][y] == 3 || w[x][y])return;
if(v[x][y] == 1)s++;
w[x][y] = 1;
dfs(x+1,y);dfs(x-1,y);dfs(x,y-1);dfs(x,y+1);
}//种子填充dfs查找房间面积
void chan(){
memset(w,0,sizeof(w));//清零bool数组
for(int j = 2;j <= 2*m;j++){//从左下角枚举到右上角,因为有多解时选最靠西的,仍然有多解时选最靠南的
for(int i = 2*n;i >= 2;i--){
if(v[i][j] == 2){
v[i][j] = 0;s = 0;//去掉墙
dfs(i,j);//去掉墙后的房间面积s
if(s > u){
u = s;//找到最大的s
if(v[i+1][j] == 1)xx1 = i+1,yy1 = j,aa = 'N';
else if(v[i][j-1] == 1)xx1 = i,yy1 = j-1,aa = 'E';
//同一格子北边的墙比东边的墙更优先
//用该墙的南邻单位的北墙或西邻单位的东墙来表示这面墙,方法是输出邻近单位的行数、列数和墙的方位
}
v[i][j] = 2;//回溯
memset(w,0,sizeof(w));//回溯
}
}
}
return;
}
int main(){
freopen("castle.in","r",stdin);
freopen("castle.out","w",stdout);
init();//输入
for(int i = 1;i <= 2 * n;i++){
for(int j = 1;j <= 2 * m;j++){
s = 0;//s为房间面积
if(v[i][j] == 1 && !w[i][j]){
ss++;dfs(i,j);
}
ans = max(ans,s);//最大房间面积
}
}//种子填充查找有几块房间以及最大的房间面积
printf("%d\n%d\n",ss,ans);
chan();
printf("%d\n%d %d %c\n",u,xx1/2,yy1/2,aa);
// xx1/2 和yy1/2是因为v数组把墙和房间放到了一起,要去掉墙
return 0;
}