1. 程式人生 > 實用技巧 >洛谷題解 P1331 海戰

洛谷題解 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;
}