题解:
这道题真的好蛋疼啊,首先题意不好理解,搞了半天复杂的要死,有那么多要求,还要求那么多东西,做到一半都不想做了。。。感觉没什么技术含量,还做起来死费劲儿。但是强迫症非得按顺序做题啊,最后还是一点点把它给调出来了,说什么flood fill,其实也就是那么回事,没什么算法上的技巧,就是见招拆招的感觉。。。
题意搞懂再做题,题意,不谢!
第一步:根据他的规则把房间画出来,遍历一遍把每个节点四面的墙给补上;
第二步:深搜;
目的1:记录深搜的次数,房间数;
目的2:记录深搜的深度,最大房间面积;
目的3:把属于同一棵树的节点标记起来,也就是染色的过程,为下一步打通房间铺路;
注意:在深搜的过程中搜的深度要注意如何保存,会有分叉以及分叉后再汇合的情况出现,我是设置了一个全局变量deep来记录深度;
第三步:打墙;
题目说了,只能打一次,而且还有规则,先紧着西边的选,如果同样靠西要先紧着南边的选,所以要注意遍历的方向。打墙的时候就凸显之前标色的重要性了,首先得找到墙,然后墙两边的颜色还要不一样,从下往上,从左往右遍历一遍找到最优解。
PS:注意数组大小。
代码实现:
/* ID: eashion LANG:C++ TASK:castle */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #define MAX 55 using namespace std; int N,M; int Sum; int Size; int deep; int BSize; int bx,by; int color; int Csize[MAX*MAX]; char oritation; int maze[MAX][MAX]; int dx[4] = {1,0,-1,0}; int dy[4] = {0,-1,0,1}; int castle[MAX*3][MAX*3]; void solve(); void dfs(int x,int y,int col); void Break(); int main() { freopen("castle.in","r",stdin); freopen("castle.out","w",stdout); scanf("%d%d",&M,&N); for( int i = 1; i <=N; i++ ){ for( int j = 1; j <= M; j++ ){ scanf("%d",&maze[i][j]); } } solve(); return 0; } void solve(){ Sum = 0; Size = 0; BSize = 0; color = 2; memset(Csize,0,sizeof(Csize)); memset(castle,0,sizeof(castle)); //补墙,用到了&运算 for( int i = 1; i <= N; i++ ){ for( int j = 1; j <= M; j++ ){ int tx = i*2-1; int ty = j*2-1; if( (maze[i][j]&1) == 1 ){ castle[tx][ty-1] = 1; } if( (maze[i][j]&2) == 2 ){ castle[tx-1][ty] = 1; } if( (maze[i][j]&4) == 4 ){ castle[tx][ty+1] = 1; } if( (maze[i][j]&8) == 8 ){ castle[tx+1][ty] = 1; } } } //补四面的墙 for( int i = 0; i <= 2*N; i++ ){ castle[i][0] = 1; } for( int i = 0; i <= 2*N; i++ ){ castle[i][2*M] = 1; } for( int i = 0; i <= 2*M; i++ ){ castle[0][i] = 1; } for( int i = 0; i <= 2*M; i++ ){ castle[2*N][i] = 1; } //补节点处的墙,其实也不太会访问到 for( int i = 2; i <= 2*N; i+=2 ){ for( int j = 2; j <= 2*M; j+=2 ){ castle[i][j] = 1; } } // for( int i = 0; i <= 2*N; i++ ){ // for( int j = 0; j <= 2*M; j++ ){ // printf("%d",castle[i][j]); // } // printf("\n"); // } //深搜 for( int i = 1; i <= N; i++ ){ for( int j = 1; j <= M; j++ ){ int tx = i*2-1; int ty = j*2-1; deep = 0; if( castle[tx][ty] == 0 ){ dfs(tx,ty,color++); Csize[color-1] = deep; Sum++; Size = max(Size,deep); } } } //打墙 Break(); printf("%d\n",Sum); printf("%d\n",Size); printf("%d\n",BSize); printf("%d %d %c\n",bx,by,oritation); } void dfs(int x,int y,int col){ //每进入一次深度+1 deep++; //标色 castle[x][y] = col; for( int i = 0; i < 4; i++ ){ int nx = x+dx[i]; int ny = y+dy[i]; int nnx = nx+dx[i]; int nny = ny+dy[i]; //必须保证两个同时为0,因为下个节点可能会已经被染色,导致重复染色 if( castle[nx][ny] == 0 && castle[nnx][nny] == 0 ){ castle[nx][ny] = col; dfs(nnx,nny,col); } } return ; } void Break(){ //注意遍历顺序 for( int j = 0; j <= 2*M; j++ ){ for( int i = 2*N; i >= 0; i-- ){ if( castle[i][j] == 1 ){ int ux,uy; int dx,dy; int rx,ry; int lx,ly; ux = i-1,uy = j; dx = i+1,dy = j; rx = i,ry = j+1; lx = i,ly = j-1; //上下打通 if( ux >= 0 && dx <= 2*N && castle[ux][uy]!=castle[dx][dy] ){ int tmp = Csize[castle[ux][uy]]+Csize[castle[dx][dy]]; if( BSize < tmp ){ BSize = tmp; bx = (dx+1)/2; by = (dy+1)/2; oritation = 'N'; } } //左右打通 if( ly >= 0 && ry <= 2*M && castle[lx][ly]!=castle[rx][ry] ){ int tmp = Csize[castle[lx][ly]]+Csize[castle[rx][ry]]; if( BSize < tmp ){ BSize = tmp; bx = (lx+1)/2; by = (ly+1)/2; oritation = 'E'; } } //把上下放前面,而且严格BSize < tmp,保证了若有可能先打‘N’ } } } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-11 00:41:34