USACO Training Section 2.1 The Castle

[url="http://ace.delos.com/usacoprob2?a=s8lALrbnS8S&S=castle"]英文原题[/url] [url="http://www.oiers.cn/usaco%20training/12-105.asp.htm"]中文题译[/url]

用深度优先或者别的搜索得到连通片(同一连通片的格子属于同一房间),由此得到房间数量(连通分量个数)和最大房间(最大连通分量的节点数)。然后再次扫描整个方格矩阵,注意每个方格有四个相邻房间(东南西北),只需扫描一半方向即可,根据题意,选择东、北方向搜索,这样得到的房间和方向可直接输出无需判重。

WA了一次,原因:把visited标志放在出栈时设导致重复访问使得得到的房间数计数错误。


/*
ID: blackco3
TASK: castle
LANG: C++
*/
#include <fstream>
using namespace std;
#define _max_ 50

int n_row, n_col, n_room, max_room_size=0 ;
int walls[_max_][_max_], room_no[_max_][_max_], visited[_max_][_max_], room_size[_max_*_max_] ;
struct t_cell {
int row, col ;
} dfs_stk[_max_*_max_];
int adj_mark[4]={1,2,4,8};
int drow[4]={0,-1,0,1}, dcol[4]={-1,0,1,0};
void get_group(int row_no, int col_no, int croom) {
t_cell *top=dfs_stk ;
top->row=row_no, top->col=col_no, top++ ;
room_size[croom]=0, visited[row_no][col_no]=1 ;
do{
--top, room_size[croom]++ ;
int crow=top->row, ccol=top->col;
room_no[crow][ccol]=croom;
for( int adj=0; adj<4; adj++ ){
if( walls[crow][ccol] & adj_mark[adj] || visited[crow+drow[adj]][ccol+dcol[adj]] )
continue ;
top->row=crow+drow[adj], top->col=ccol+dcol[adj] ;
visited[top->row][top->col]=1, top++ ;
}
}while( top!=dfs_stk );
if( max_room_size < room_size[croom] )
max_room_size = room_size[croom] ;
}

int main()
{
ifstream fin("castle.in");
ofstream fout("castle.out");
fin >> n_col >> n_row ;
int irow, icol ;
for( irow=0; irow<n_row; irow++){
for( icol=0; icol<n_col; icol++ ){
fin >> walls[irow][icol] ;
room_no[irow][icol]=-1, visited[irow][icol]=0 ;
}
}
for( irow=0, n_room=0; irow<n_row; irow++){
for( icol=0; icol<n_col; icol++ ){
if( room_no[irow][icol]!=-1 )
continue ;
get_group(irow, icol, n_room++);
}
}
fout << n_room << endl << max_room_size << endl ;
int max_merge=0, mrow, mcol, mwall;
for( irow=0; irow<n_row; irow++){
for( icol=0; icol<n_col; icol++ ){
for( int adj=1; adj<3; adj++ ){
int adj_row=irow+drow[adj], adj_col=icol+dcol[adj];
if( adj_row<0 || adj_col>=n_col || room_no[adj_row][adj_col]==room_no[irow][icol] )
continue ;
int merge_size = room_size[room_no[adj_row][adj_col]] + room_size[room_no[irow][icol]];
if( max_merge > merge_size )
continue ;
if( max_merge < merge_size ){
max_merge=merge_size, mrow=irow, mcol=icol, mwall=adj ;
} else {
if( mcol>icol || ( mcol==icol && mrow<irow ) )
mrow=irow, mcol=icol, mwall=adj ;
}
}
}
}
fout << max_merge << endl ;
fout << mrow+1 << " " << mcol+1 << " " << (mwall==1 ? "N" : "E") << endl ;
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值