P1457 城堡 The Castle

https://www.luogu.org/problemnew/show/P1457

用struct记录一下城堡的墙面情况(根据输入的数据来确定)
首先dfs记一下每个联通块大小,再枚举每个格子的东墙、北
墙被打通之后连接起来的两个联通块大小,有如下两种状况
1、若大于sum则更新sum,方格位置,墙的方位
2、若等于sum,则看一下这个格子在原来格子西面或者下面则更新
格子位置,这个格子跟之前格子是同一个,则更新墙的方位为北

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll ,ll > P;
#define INF 0xf3f3f3f
const int Max=int(5e5+10);
int m,n;
struct point {
	int a[4];// 0xi 1nan  2bei  3dong
	int value;
	int key;
} mm[55][55];
bool vis[55][55];
int dx[4]= {0,1,-1,0};
int dy[4]= {-1,0,0,1};
int kuai[55*55];
int num,sum,ma;
void pan(point &x) {
	switch(x.value) {
		case 1:
			x.a[0]=1,x.a[1]=0,x.a[2]=0,x.a[3]=0;
			break;
		case 2:
			x.a[0]=0,x.a[1]=0,x.a[2]=1,x.a[3]=0;
			break;
		case 3:
			x.a[0]=1,x.a[1]=0,x.a[2]=1,x.a[3]=0;
			break;
		case 4:
			x.a[0]=0,x.a[1]=0,x.a[2]=0,x.a[3]=1;
			break;
		case 5:
			x.a[0]=1,x.a[1]=0,x.a[2]=0,x.a[3]=1;
			break;
		case 6:
			x.a[0]=0,x.a[1]=0,x.a[2]=1,x.a[3]=1;
			break;
		case 7:
			x.a[0]=1,x.a[1]=0,x.a[2]=1,x.a[3]=1;
			break;
		case 8:
			x.a[0]=0,x.a[1]=1,x.a[2]=0,x.a[3]=0;
			break;
		case 9:
			x.a[0]=1,x.a[1]=1,x.a[2]=0,x.a[3]=0;
			break;
		case 10:
			x.a[0]=0,x.a[1]=1,x.a[2]=1,x.a[3]=0;
			break;
		case 11:
			x.a[0]=1,x.a[1]=1,x.a[2]=1,x.a[3]=0;
			break;
		case 12:
			x.a[0]=0,x.a[1]=1,x.a[2]=0,x.a[3]=1;
			break;
		case 13:
			x.a[0]=1,x.a[1]=1,x.a[2]=0,x.a[3]=1;
			break;
		case 14:
			x.a[0]=0,x.a[1]=1,x.a[2]=1,x.a[3]=1;
			break;
		case 15:
			x.a[0]=1,x.a[1]=1,x.a[2]=1,x.a[3]=1;
			break;

	}
}
void dfs(int x,int y,int c) {
	kuai[c]++;
	mm[x][y].key=c;
	for(int i=0; i<4; i++) {
		int tx=x+dx[i];
		int ty=y+dy[i];
		if(tx>0&&tx<=n&&ty>0&&ty<=m)
			if(!vis[tx][ty]&&!mm[x][y].a[i]) {
				vis[tx][ty]=1;
				dfs(tx,ty,c);
			}
	}
}
int main() {
	scanf("%d%d",&m,&n);
	memset(vis,0,sizeof vis);
	num=0,sum=0,ma=0;
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++) {
			scanf("%d",&mm[i][j].value);
			pan(mm[i][j]);
		}
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++) {
			if(!vis[i][j]) {
				++num;
				vis[i][j]=1;
				mm[i][j].key=num;
				dfs(i,j,num);
				ma=max(ma,kuai[num]);
			}
		}
	printf("%d\n%d\n",num,ma);
	int x,y;
	char c;
	for(int i=n; i>0; i--)
		for(int j=1; j<=m; j++) {
					if(mm[i][j].a[2]) {
				int tx=i+dx[2];
				int ty=j+dy[2];
				if(tx>0&&tx<=n&&ty>0&&ty<=m) {
					int x1=mm[tx][ty].key;
					int x2=mm[i][j].key;
					if(x1!=x2) {
						int tt=kuai[x1]+kuai[x2];
						if(tt>=sum) {
							if(tt>sum) {
								sum=tt;
								x=i,y=j,c='N';
							} else {
								if((j<y)||(j==y&&i>x)) {
									sum=tt;
									x=i,y=j,c='N';
								}
								if(i==x&&j==y)
									c='N';
							}
						}
					}
				}

			}
			if(mm[i][j].a[3]) {
				int tx=i+dx[3];
				int ty=j+dy[3];
				if(tx>0&&tx<=n&&ty>0&&ty<=m) {
					int x1=mm[tx][ty].key;
					int x2=mm[i][j].key;
					if(x1!=x2) {
						int tt=kuai[x1]+kuai[x2];
						if(tt>=sum) {
							if(tt>sum) {
								sum=tt;
								x=i,y=j,c='E';
							} else if((j<y)||(j==y&&i>x)) {
								sum=tt;
								x=i,y=j,c='E';
							}
						}
					}
				}
			}
			
	
		}
	printf("%d\n",sum);
	printf("%d %d %c\n",x,y,c);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值