USACO :The Castle解题报告

      这是道floodfill题,用DFS对每个square扩展很容易得到room的个数以及面积大小。square扩展时用到位运算,每次扩展到下一个square,应将扩展的入口堵住,避免重复扩展甚至死循环。然后枚举打开每一堵墙(最外围的墙除外),当墙两边不属于同一个房间且面积之和最大时即得解。为了避免排序,应从西向东,从南向北的顺序枚举。
/*
ID: xpli1
PROG: castle
LANG: C++
*/

#include <iostream>
#include <fstream> 
#include <cstdio>
#include <cmath>
using namespace std;

#define OUT cout
#define IN  cin
#define MAXNUM 51*51

ofstream fout ("castle.out");
ifstream fin ("castle.in");

int wall[MAXNUM];
int sq_rm[MAXNUM];
int sq_num[MAXNUM];
int M,N;
int roomnum;
int max_sq_num = -1;
int max_sq_num_move = -1;
int ii,jj;
char direction;

void dfs(int k,int dir){
 if(sq_rm[k]) return;
 sq_rm[k] = roomnum;    
 sq_num[roomnum]++;
 int WALL = wall[k]+dir;  // 将入口堵住
 if(!(WALL & 1)) dfs(k-1,4);
 if(!(WALL & 2)) dfs(k-M,8);
 if(!(WALL & 4)) dfs(k+1,1);
 if(!(WALL & 8)) dfs(k+M,2);
}

void mkbigest(){
 int i,j;
 for(i=0; i<N; i++){
  wall[i*M + 0] -= 1;
  wall[i*M + M-1] -= 4;
 }
 for(i=0; i<M; i++){
  wall[i] -= 2;
  wall[(N-1)*M+i] -= 8;
 }
 
 int index,rmnum;
 for(j=0; j<M; j++){
  for(i=N-1; i>=0; i--){
   index = i*M+j;
   if(wall[index]&2 && sq_rm[index] != sq_rm[index-M]){
    rmnum = sq_num[sq_rm[index]]+sq_num[sq_rm[index-M]];
    if(max_sq_num_move < rmnum){
     max_sq_num_move = rmnum;
     ii = i+1;
     jj = j+1;
     direction = 'N';
    }
   }
  }
  for(i=N-1; i>=0; i--){
   index = i*M+j;
   if(wall[index]&4 && sq_rm[index] != sq_rm[index+1]){
    rmnum = sq_num[sq_rm[index]]+sq_num[sq_rm[index+1]];
    if(max_sq_num_move < rmnum){
     max_sq_num_move = rmnum;
     ii = i+1;
     jj = j+1;
     direction = 'E';
    }
   }
  }
 }
}

int main()
{
 IN >> M >> N;
 int i;
 for(i=0; i<M*N; i++)
  IN >> wall[i];

 for(i=0; i<M*N; i++){
  if(sq_rm[i]) continue; 
  roomnum++;
  dfs(i,0); 
 } 
 OUT<< roomnum << endl;

 for(i=0; i<roomnum+1; i++){
  if(max_sq_num < sq_num[i])
   max_sq_num = sq_num[i];
 }
 OUT << max_sq_num << endl;

 mkbigest();
 OUT << max_sq_num_move << endl;
 OUT << ii << ' ' << jj << ' '<< direction << endl;

 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值