BFS——关于洛谷P1331海战的思考
题目链接:https://www.luogu.com.cn/problem/P1331
解题的主要思路;1.如何判断是否是Bad placement的情况,这里是先观察到如果是Bad placement必然会有如下结构,其实也蛮好想的,如果是一个整体的船则必然是方形,否则就是多边形,这必然带有如下结 构,反过来也一样,然后就两个for循环一个个判断即可。

2.如果不是Bad placement,本题目就变换为了求连通块的问题,可以用DFS也可以BFS,这里我选择用BFS。
AC代码展示:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m; 4 char s[2000][2000]; 5 int book[2000][2000]; 6 int dis[4][2]={{-1,0},{0,1},{1,0},{0,-1}}; 7 //判断是否碰船了 这个思路值得学习 8 bool p(){ 9 for(int i=0;i<n;i++){ 10 for(int j=0;j<m;j++){ 11 if((n-i)>=1&&(m-j)>=1){ 12 int ans=0; 13 if(s[i][j]=='#'){ 14 ans++; 15 } 16 if(s[i][j+1]=='#'){ 17 ans++; 18 } 19 if(s[i+1][j]=='#'){ 20 ans++; 21 } 22 if(s[i+1][j+1]=='#'){ 23 ans++; 24 } 25 if(ans==3){ 26 return false; 27 } 28 } 29 } 30 } 31 return true; 32 } 33 int main(){ 34 scanf("%d%d",&n,&m); 35 getchar(); 36 getchar(); 37 for(int i=0;i<n;i++){ 38 for(int j=0;j<m;j++){ 39 scanf("%c",&s[i][j]); 40 } 41 getchar(); 42 getchar(); 43 } 44 int flag=0; 45 if(!p()){ 46 cout<<"Bad placement."<<endl; 47 }else{ 48 for(int i=0;i<n;i++){ 49 for(int j=0;j<m;j++){ 50 if(book[i][j]==0&&s[i][j]=='#'){ 51 flag++; 52 queue<int>xx; 53 queue<int>yy; 54 xx.push(i); 55 yy.push(j); 56 book[i][j]=1; 57 while(!xx.empty()){ 58 int x1=xx.front(); 59 int y1=yy.front(); 60 xx.pop(); 61 yy.pop(); 62 for(int k=0;k<4;k++){//这里注意不能是i或者j 因为可能会re 63 int x=x1+dis[k][0]; 64 int y=y1+dis[k][1]; 65 if(book[x][y]==0&&(x>=0&&x<n)&&(y>=0&&y<m)&&s[x][y]=='#'){ 66 xx.push(x); 67 yy.push(y); 68 book[x][y]=1; 69 } 70 } 71 } 72 } 73 } 74 } 75 cout<<"There are "<<flag<<" ships."<<endl; 76 //int main返回一个非零的数会报错 会runtime erro 77 } 78 }
注意事项:1.BFS的大概框架:

2.有两个getchar()是为了清除缓存区的换行符,linux系统下的换行符为/r/n,而windows中就转化为了一个/n,这就是洛谷提交要用两个getchar(),本地windows则只需要用到一个getchar(),如果不用 清除缓存区的换行符,就会被scanf(应为是%c,scanf要读入字符)读入,发生错误.
3.用scanf一个一个读入字符,比用cin读入string块多了,在大数据面前更加明显.
4.main函数不要返回一个非零值,不然洛谷判题机会re(runtime error)

浙公网安备 33010602011771号