此题在Openjudge NOI 上面还有一个阉割版,也就是只求最大房间大小和房间总数量,在2.5搜索专题里面。阉割版不需要多思考就可以做出来,不过原版也只是在想一步而已,鉴于数据不是特别大。可以看到我的做法就是先BFS 算房间,把每个块所属的房间和大小记录好,然后再 按 顺 序 枚举每个块,从而得出做大合并房间和推倒位置。判断墙的存在时用了位运算,因为题目的1248明显就是暗示要这么搞最方便。
1 #include<queue> 2 #include<iostream> 3 using namespace std; 4 const int N=64,ax[]={0,0,1,-1,0},ay[]={0,-1,0,0,1},dr[]={0,1,8,2,4}; 5 const char conv[]={‘\0‘,‘W‘,‘S‘,‘N‘,‘E‘}; 6 struct pnt{int x,y;pnt(int n1,int n2):x(n1),y(n2){}}; 7 int r,c,arg[N][N]; 8 int rooms=1,largest,ans,fnx,fny,fnd,size[N],code[N][N]; 9 bool bfsed[N][N]; 10 int bfs(int sx,int sy){ 11 int res=1; 12 queue<pnt> q; 13 q.push(pnt(sx,sy)); 14 bfsed[sx][sy]=true; 15 code[sx][sy]=rooms; 16 while(!q.empty()){ 17 int x=q.front().x,y=q.front().y; 18 q.pop(); 19 for(int i=1;i<=4;i++){ 20 int nx=x+ax[i],ny=y+ay[i]; 21 if(nx<1||nx>r||ny<1||ny>c||bfsed[nx][ny]||arg[x][y]&dr[i])continue; 22 res++; 23 bfsed[nx][ny]=true; 24 code[nx][ny]=rooms; 25 q.push(pnt(nx,ny)); 26 } 27 } 28 return res; 29 } 30 int main(){ 31 cin>>c>>r; 32 for(int i=1;i<=r;i++) 33 for(int j=1;j<=c;j++) 34 cin>>arg[i][j]; 35 for(int i=1;i<=r;i++) 36 for(int j=1;j<=c;j++) 37 if(!bfsed[i][j]) 38 largest=max(largest,size[rooms]=bfs(i,j)),rooms++; 39 for(int j=c;j>=1;j--) 40 for(int i=1;i<=r;i++){ 41 if(i>1&&(arg[i][j]&2)&&code[i][j]!=code[i-1][j]){ 42 if(size[code[i-1][j]]+size[code[i][j]]>=ans){ 43 ans=size[code[i-1][j]]+size[code[i][j]]; 44 fnx=i;fny=j;fnd=3; 45 } 46 } 47 else if(j<c&&(arg[i][j]&4)&&code[i][j]!=code[i][j+1]){ 48 if(size[code[i][j+1]]+size[code[i][j]]>=ans){ 49 ans=size[code[i][j+1]]+size[code[i][j]]; 50 fnx=i;fny=j;fnd=4; 51 } 52 } 53 } 54 cout<<rooms-1<<endl<<largest<<endl<<ans<<endl 55 <<fnx<<" "<<fny<<" "<<conv[fnd]<<endl; 56 return 0; 57 }
Method_01
洛谷上3ms。
时间: 2024-10-06 19:02:44