洛谷题解 P1331 海战

原题传送门

0.前言 依旧是一个简单的搜索训练呢...

1.算法 DFS或BFS均可(此处使用DFS)

2.思路
看见样例,依然还是一道简单的搜索题。
这道题在原先是 普及/提高- 的题,后来是不是因为太简单被调了
可以把这道题主要要完成的操作:

  • 搜索+统计船的个数
  • 判断是否有船相邻

其中第一个操作非常好完成。就是就是一个简单的搜索遍历。
但是第二个操作就有些难度。
这里需要运用到一些技巧(找规律)
通过找规律我们可以发现,当在相邻的4个方格中,有三个是“*”时,则船会相邻
因为只能出现一下这四种不合法的情况:

 * *       * *       * .       . *  
 * .       . *       * *       * *

3.代码

#include<iostream>
#include<cstdio>
using namespace std;
inline void read(int &x){	//快读 
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int x,y;
char map[1001][1001];	//存图 
int dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1};	//上下左右遍历的辅助数组 
inline bool judge(int m,int n){	//判断是否有船相邻的情况 
	int cnt=0;
	if(map[m][n]=='#') cnt++;
	if(map[m+1][n]=='#') cnt++;
	if(map[m][n+1]=='#') cnt++;
	if(map[m+1][n+1]=='#') cnt++;
	if(cnt==3) return false;
	else return true;
}
inline void DFS(int p,int q){	 
	map[p][q]='^';	//把与当前(即"#")节点标成一个统一的符号
	//为了和原"#"区分(因为是同一艘船) 
	for(int i=1;i<=4;i++){
		if(p+dx[i]<0||p+dx[i]>x+1||q+dy[i]<0||q+dy[i]>y+1) continue;	//边界条件不要忘 
		if(map[p+dx[i]][q+dy[i]]=='#'){		//当前节点也是船的时候才能继续遍历 
			DFS(p+dx[i],q+dy[i]);
		} 
 	} 
}
int ans;
int main(){
	read(x);read(y);
	for(int i=1;i<=x;i++){
		for(int j=1;j<=y;j++){
			cin>>map[i][j];
		}
	}
	for(int i=1;i<=x;i++){
		for(int j=1;j<=y;j++){
			if(judge(i,j)==false){
				printf("Bad placement.");	//注意句号qwq 
				return 0;
			}
		}
	}
	for(int i=1;i<=x;i++){
		for(int j=1;j<=y;j++){
			if(map[i][j]=='#'){	//只要有"#",就有一艘船 
				ans++;	 
				DFS(i,j);	//把整艘船全部搜出来 
			}
		}
	}
	printf("There are %d ships.",ans);	//注意句号qwq 
	return 0;
}
原文地址:https://www.cnblogs.com/-pwl/p/13647612.html