实验二搜索

本文介绍了如何使用深度优先搜索(DFS)和广度优先搜索(BFS)解决LeetCode中的n皇后问题,以及在其他场景(如棋盘冲突检查、岛屿连接计算和路径寻找)中的应用。
摘要由CSDN通过智能技术生成

练习题

  1. leetcode组合数
  2. n皇后

leetcode___n皇后

class Solution {
public:
    vector<vector<string>> result;

    bool isValid(int row, int col, vector<string>& chessboard, int n) {
        //检查列
        for(int i=0; i<row; i++){
            if(chessboard[i][col]=='Q'){
                return false;
            }
        }
        //检查45度角
        for(int i = row-1, j= col-1; i>=0&&j>=0; i--, j--){
            if(chessboard[i][j]=='Q'){
                return false;
            }
        }
        //检查135度角
        for(int i=row-1, j=col+1; i>=0&&j<n; i--, j++){
            if(chessboard[i][j]=='Q'){
                return false;
            }
        }
        return true;
    }

    void dfs(vector<string>& chessboard, int n) {
        if (chessboard.size() == n) {
            result.push_back(chessboard);
            return;
        }
        int row = chessboard.size();
        for (int col = 0; col < n; col++) {
            
            if (isValid(row, col, chessboard, n)) {
                string str(n, '.');
                chessboard.push_back(str);
                chessboard[row][col] = 'Q';
                dfs(chessboard, n);
                chessboard.pop_back();
            }
           
        }
    }

    vector<vector<string>> solveNQueens(int n) {
        vector<string> chessboard;
        dfs(chessboard, n);
        return result;
    }
};

1.connected blocks

Hoenn

描述

Hoenn was created by Groudon and Kyogre. Groudon raised the landmasses (a landmass is represented by "o") and Kyogre filled the seas (a sea is represented by "a"), and thus Hoenn was created. A meeting between these two caused a great battle for supremacy until it was quelled by Rayquaza, sending Groudon and Kyogre into caverns where they rested. Nowadays, Hoenn people want to know the size of the biggest connnected seas filled by Kyogre which equals to the biggest size of connected blocks formed by character "a" (Up, Down, Left, Right).

输入

Each test case contains a single integer N (N < 1000), the length and also the width of Hoenn. Next N lines will be the result of the battle. "o" means a landmass and "a" means a sea. The input is terminated when N = 0.

输出

For each test case, you must print the size of the biggest connnected seas filled by Kyogre.

题解

  1. dfs,从每个位置开始dfs搜索,返回最大的
  2. 撤销操作体现在哪里呢??????
#include<bits/stdc++.h>
using namespace std;

int dfs(vector<vector<char>>& graph, vector<vector<int>>& visited, int i, int j, int n){
	if(i<0 || i>=n || j<0 || j>=n || graph[i][j]=='o' || visited[i][j]){
		return 0;
	}
	visited[i][j] = 1;
	int ret = 1;
	ret += dfs(graph, visited, i+1, j, n);
	ret += dfs(graph, visited, i, j+1, n);
	ret += dfs(graph, visited, i-1, j, n);
	ret += dfs(graph, visited, i, j-1, n);
	return ret;
}

int main(){
	int n;
	while(cin >> n && n!=0){
		//(1)处理输入 
		vector<vector<char>> graph(n, vector<char>(n));
		vector<vector<int>> visited(n, vector<int>(n, 0));
		for(int i=0; i<n; i++){
			for(int j=0; j<n; j++){
				cin >> graph[i][j];
			}
		}
		
		//(2)从每个位置开始dfs
		int ans = -1;
		for(int i=0; i<n; i++){
			for(int j=0; j<n; j++){
				ans = max(ans, dfs(graph, visited, i, j, n));
			}
		}
		cout << ans << endl; 
	}	
}

2.拓扑排序

Winner of teams

描述

There are N teams (1<=N<=500), numbered 1, 2, 3, …, N, in a competition. At the end of the competition, the referee committee have to rank all the teams from the first to the last. Unfortunately, the referee committee cannot get the score of each team directly. They only know the result of each match, that is, when P1 wins against P2, P1 is ranked before P2. Now you need to program to determine the ranking.

输入

There are several groups of input, and the first row in each group includes two numbers N (1<=N<=500), and M, where N represents the number of teams and M means there are M lines of input data following the first row of each group. In the next M rows, each row also includes two integers P1 and P2, meaning that team P1 wins against team P2.

输出

Give a ranking that meets the requirements. Output with a space between two team numbers and no space after the last one.

题解

  1. 邻接表存储有向图,数组存储顶点的入度
  2. 使用优先队列来存储入度为0的点
    1. 保存该点并弹出,
    2. 遍历该点的邻接点,使其入度减一,并检查入度是否降为0
      1. 是:加入到优先队列
      2. 否,继续
#include<bits/stdc++.h>
using namespace std;

int main(){
	int n, m;
	while(cin >> n >> m){
		//(1)处理输入,构建邻接表,入度表
		vector<int> inDegree(n+1, 0);
		vector<vector<int>> graph(n+1);
		for(int i=0; i<m; i++){
			int p1, p2;
			cin >> p1 >> p2;
			graph[p1].push_back(p2);
			inDegree[p2]++;
		}
		
		//(2)拓扑排序
		priority_queue<int, vector<int>, greater<int>> pq;
		for(int i=1; i<=n ;i++){
			if(inDegree[i]==0){
				pq.push(i);
			}
		}
		vector<int> result;
		while(!pq.empty()){
			int cur = pq.top();
			cout << "cur=" << cur <<endl;
			pq.pop();
			result.push_back(cur);
			for(int adj: graph[cur]){
				inDegree[adj]--;
				if(inDegree[adj]==0){
					pq.	
				}
			}
		}
		//(3)输出结果
		for(int i=0; i<n ;i++){
			if(i>0) cout <<" ";
			cout << result[i];
		} 
		cout << endl;
	}
}

3.n皇后问题

Alola

描述

Alola consists of four tropical islands. Hala, the island owner of one of these four tropical islands, wants to plant �N different trees to form a forest. It is required tht any two different trees cannot be in the same row, the same column, or the same diagonal with a 45 degree angle. Could you compute how many ways there are to put the trees?

输入

The input includes multiple test cases. Each test case contains an integer �(�&lt;=10)N(N<=10), which means the size of the forest (�∗�)(N∗N) and the number of different trees.

输出

For each test case, you must print a line which includes the number of ways to put the trees.

题解

#include<bits/stdc++.h>
using namespace std;

//row表示要放的这一层 
bool isValid(vector<vector<int>>& chessboard, int row, int col, int n){
	//检查列
	for(int i=0; i<row; i++){
		if(chessboard[i][col]==1){
			return false;
		}
	}
	//检查45度
	for(int i = row-1, j = col+1; i>=0&&j<n; i--,j++){
		if(chessboard[i][j]){
			return false;
		}
	}
	//检查135度
	for(int i=row-1, j=col-1; i>=0&&j>=0; i--,j--){
		if(chessboard[i][j]){
			return false;
		}
	}
	return true; 
}

int dfs(vector<vector<int>>& chessboard, int n, int row){
	//(1)递归,遍历层数 
	if(row==n-1){
		return 1;
	}
	int ret = 0;
	//(2)循环,遍历列数 
	for(int col=0; col<n; col++){
		if(isValid(chessboard, row+1, col, n)){
			chessboard[row+1][col] = 1;
			ret += dfs(chessboard, n, row+1);
			//(3)撤销操作 
			chessboard[row+1][col] = 0;
		}
	}
	return ret;
}

int main(){
	int n;
	while(cin >> n){
		vector<vector<int>> chessboard(n ,vector<int>(n, 0));
		int ans = dfs(chessboard, n, -1);
		cout << ans << endl;
	}
}

 4.simple dfs

Sinnoh

描述

In Sinnoh's mythology, Arceus created Dialga, Palkia, and Giratina. Arceus then gave Dialga and Palkia the abilities to control time and space respectively. Giratina was banished to another dimension, a Distortion World, for its violent behavior. One day, Giratina was at a special room, which was coverd by blocks from the Distortion World and the Real World. Giratina was at a Distortion World block. From a block, he can move to one of four adjacent blocks. However, he can move only on Distortion World blocks. Can you tell the number of Distortion World blocks which Giratina can reach by repeating the moves described above?

输入

Each test case starts with a line containing two positive integers �W and �H (�,�&lt;=100)(W,H<=100), meaning the numbers of blocks in the x- and y- directions, respectively. There are �H more lines in the case, each of which includes �W characters, and each character represents the type of a block as follows.

'D' - Distortion World block; 'R' - Real World block; 'G' - Giratina on a Distortion World block (appears exactly once in a case.)

The inputs will be terminated at the end of the file (EOF).

输出

For each test case you must print a line which contains the number of blocks Giratina can reach from the initial block (including itself).

题解

#include<bits/stdc++.h>
using namespace std;

int w, h;

int dfs(vector<vector<char>>& graph, vector<vector<int>>& visited, int x, int y){
	if(x<0 || y<0 || y>=w || x>=h || visited[x][y] || graph[x][y]=='R'){
		return 0;
	}
	visited[x][y] = 1;
	int ret = 1;
	ret += dfs(graph, visited, x+1, y);
	ret += dfs(graph, visited, x, y+1);
	ret += dfs(graph, visited, x-1, y);
	ret += dfs(graph, visited, x, y-1);
	return ret;
}

int main(){
	int x, y;
	while(cin >> w >> h){
		vector<vector<char>> graph(h, vector<char>(w));
		vector<vector<int>> visited(h, vector<int>(w, 0));
		for(int i=0; i<h; i++){
			for(int j=0; j<w; j++){
				cin >> graph[i][j];
				if(graph[i][j]=='G'){
					x = i;
					y = j;	
				}
			}
		}
		int ans = dfs(graph, visited, x, y);
		cout << ans << endl;
	}
}

5.广度优先搜索求最短路径

Mewtwo

描述

Researchers of Kanto did a great job. A researcher working for the organization Team Rocket cloned Mew by using its genes and created Mewtwo. However, he cannot control Mewtwo and it wanted to escape. Could you tell how many steps Mewtwo needs to take to escape?

输入

Each test case contains a single integer �N (�&lt;1000)(N<1000), the length and also the width of the house of Team Rocket. The next �N lines will be the map. Mewtwo started at �M, and the door was at �D.  means a wall that Mewtwo cannot go through. Mewtwo can only go vertically and horizontally. The input will be terminated when �=0N=0. (Each test case contains an �M and a �D)

输出

For each test case, you must print the minimum number of steps that Mewtwo needs to take to escape, or −1−1 if Mewtwo cannot escape from Team Rocket.

题解

1.dfs

2.bfs

#include<bits/stdc++.h>
using namespace std;

/*
1.dfs解法
2.bfs解法 
*/
int n;
bool flag;
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1}; 
int bfs(vector<vector<char>>& graph, vector<vector<int>>& visited, int n, int x, int y){
	queue<pair<pair<int, int>, int>> q;//((row, col), step);
	q.push({{x, y}, 0});
	while(!q.empty()){
		pair<pair<int, int>, int> cur = q.front();
		q.pop();
		int x = cur.first.first;
		int y = cur.first.second;
		visited[x][y] = 1;
		int step = cur.second;
		int nx, ny;
		for(int i=0; i<4; i++){
			nx = x + dx[i];
			ny = y + dy[i];
			if(nx>=0 && ny>=0 && nx<n && ny<n && !visited[nx][ny]){
				if(graph[nx][ny]=='D'){
					return step+1;
				}
				if(graph[nx][ny]=='@'){
					q.push({{nx, ny}, step+1});
					visited[nx][ny] = 1;
				}
			}
		}	
		
	}
	return -1;	
} 


int dfs(vector<vector<char>>& graph, vector<vector<int>>& visited, int n, int x, int y){
	if(x<0 || y<0 || x>=n || y>=n || graph[x][y]=='#' || visited[x][y]){
		return 1000000;
	}
	if(graph[x][y]=='D'){
		flag = true;
		return 0;	
	}
	visited[x][y] = 1;
	int a = dfs(graph, visited, n, x+1, y) + 1;
	int b = dfs(graph, visited, n, x, y+1) + 1;
	int c = dfs(graph, visited, n, x-1, y) + 1;
	int d = dfs(graph, visited, n, x, y-1) + 1;
	return min(min(a,b), min(c, d));
}

int main(){
	int x, y;
	while(cin >> n && n!=0){
		vector<vector<char>> graph(n, vector<char>(n));
		vector<vector<int>> visited(n, vector<int>(n, 0));
		flag = false;
		for(int i=0; i<n; i++){
			for(int j=0; j<n; j++){
				cin >> graph[i][j];
				if(graph[i][j]=='M'){
					x = i;
					y = j;
				}	
			}
		}
		
//		int ans = dfs(graph, visited, n, x, y);
//		if(flag)
//			cout << ans << endl;
//		else
//			cout << -1 << endl;	

		int ans = bfs(graph, visited, n, x, y);
		cout << ans << endl;
	}	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值