http://train.usaco.org/usacoprob2?a=ZSn5SwI7CNy&S=castle
题目大意:给个m*n的图,每个格子里是数字,代表四个方向有没有墙。求有几个房间,最大房间面积,拆掉某墙后最大房间面积,拆掉哪座墙。
简直太坑。。写了一天最后发现最关键的34问思路有问题,于是看了看别人的解题报告,把所有代码删了重写。
重写之后的代码短了一半。。
关键点:拆掉某墙之后最大房间面积。此时只需要遍历所有墙。也不算慢,直接比较拆后和当前最大谁大。这一步也可以解决拆哪座墙的问题。
之前的思路错在:先判断房间之间是否相邻,再算合并面积。这样只能有效解决3,而且浪费空间,多开个数组记录是否相邻。而且,如果有两个房间加起来面积一样大,就很难解决4的问题。
还是得学会用计算机的思维解决问题qwq
代码:
/*
PROG: castle
ID : 49743541
LANG: C++
*/
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
typedef struct{
bool dong;
bool xi;
bool nan;
bool bei;
}room;
int map[52][52];
int color[52][52];
room r[52][52];
int amount[2504];//不同颜色房间的大小
int c;
int row,column;
void wall(int i,int j){ //判断这个格子的四个方向有没有墙
if(map[i][j]&1) r[i][j].xi = 1;
if(map[i][j]&2) r[i][j].bei = 1;
if(map[i][j]&4) r[i][j].dong = 1;
if(map[i][j]&8) r[i][j].nan = 1;
// printf("%d %d %d %d\n",r[i][j].dong,r[i][j].nan,r[i][j].xi,r[i][j].bei);
return;
}
void Floodfill(int i,int j){ //
if(color[i][j])//不用判断越界,因为边界一定有墙,搜不出去
return;
color[i][j] = c;
amount[c]++;//统计数目
if(!r[i][j].xi) Floodfill(i,j-1);
if(!r[i][j].bei) Floodfill(i-1,j);
if(!r[i][j].dong) Floodfill(i,j+1);
if(!r[i][j].nan) Floodfill(i+1,j);
return;
}
int main(){
freopen("castle.in", "r", stdin);
freopen("castle.out", "w", stdout);
scanf("%d%d",&column,&row);
for(int i = 0;i<row;i++)
for(int j = 0;j<column;j++){
scanf("%d",&map[i][j]);
wall(i,j);//判断房间周围的墙
}
for(int i = 0;i<row;i++)
for(int j = 0;j<column;j++){
if(!color[i][j]){
c++;
Floodfill(i,j);
}
}
printf("%d\n",c);//房间数量
int maxarea = 0;
for(int i = 1;i<=c;i++)
maxarea = max(maxarea,amount[i]);//遍历,找出最大房间面积
printf("%d\n",maxarea);
int maxcarea = 0;
int x = 0;
int y = 0;//满足条件的格子坐标
char c;//满足条件的墙方向
int ca,cb;
for(int i = 0;i<row;i++)
for(int j = 0;j<column;j++){//因为题目只说了两个方向,所以只用考虑两个方向
ca = color[i][j];
if(i>=0 && j+1<=column-1 && color[i][j]!=color[i][j+1] && r[i][j].dong){//注意优先级!!
cb = color[i][j+1];
if(maxcarea<amount[ca]+amount[cb]){
maxcarea = amount[ca]+amount[cb];
x = i;
y = j;
c = 'E';
}
else if(maxcarea==amount[ca]+amount[cb]){
if(j<y){
y = j;
x = i;
c = 'E';
}
if(j==y){
if(i>x) {
x = i;
c = 'E';
}
}
}
}
if(i-1>=0 && j>=0 && color[i][j]!=color[i-1][j] && r[i][j].bei){
cb = color[i-1][j];
if(maxcarea<amount[ca]+amount[cb]){
maxcarea = amount[ca]+amount[cb];
x = i;
y = j;
c = 'N';
}
else if(maxcarea==amount[ca]+amount[cb]){
if(j<y){
y = j;
x = i;
c = 'N';
}
if(j==y){
if(i>x) x = i;
if(i==x)
c = 'N';
}
}
}
}
printf("%d\n",maxcarea);
printf("%d %d %c\n",x+1,y+1,c);
/*
for(int i = 0;i<row;i++){
printf("\n");
for(int j = 0;j<column;j++){
printf("%d ",color[i][j]);
}
}*/
// printf("%d",amount[2]);
return 0;
}
本文探讨了USACO竞赛中的一道题目——The Castle,涉及使用DFS解决Flood Fill问题。作者分享了在解决过程中遇到的困难,如错误的解题思路,以及如何通过重新思考和简化代码来提高效率。关键点在于评估拆掉墙体后的最大房间面积,通过遍历所有墙体直接比较。原先的解决方案因判断相邻房间和额外记录数组而效率低下,最终得出使用计算机思维解决问题的重要性。
431

被折叠的 条评论
为什么被折叠?



