CCF 201312-5

算法思想:使用广度优先遍历(队列实现)

步骤:1、从起点S开始广度优先遍历整个图,使用visited向量(数组)保存每个点是否被访问过;

           2、判断终点T是否被访问,即visited[T]是否为1;

           3、若为0,输出“I'm xxx”;

           4、否则,根据visited数组中的记录,将那些S可以到达的点(除了S和T之外),依次作为起点,广度优先遍历整张图,使用数组/向量vec保存其他点是否被访问过,若在遍历过程中,经过了T,即vec[T]=1,结束遍历,记录这个点可以到达终点(index[N]=1),这种情况不是我们要的情况;

  若在遍历过程中,经过了一个点m,它在之前的判断中,已经被证明可以到达(index[M]=1),那么也结束遍历,记录这点可到达终点;

若在遍历过程中,没有出现上述两种情况,就是我们想要的点,计数器可以加一

(注意一下的实现中,num作为计数器,并不是在想要的情况+1,而是在不是想要的情况下,退出遍历的循环时-1实现的。)

以下为代码实现,确实不简洁,我也不想改了,顶多改改遍历那里的循环过程,没什么简化的意思,因为思想都一样。

#include<iostream>
#include<queue>
#include<string>
#include<vector>
using namespace std;
void setALL(vector<int>& vec, int valuse) {
	for (int i = 0; i < vec.size(); i++)
		vec[i] = valuse;
}
int main() {
	int rowcount;
	int colcount;
	cin >> rowcount;
	cin >> colcount;
	vector<int> flag;
	int s;
	int t;
	//处理字符串,每个字符可以行走的方向用flag保存
	for (int i = 0; i < rowcount; i++) {
		string str;
		cin >> str;
		for (int j = 0; j < colcount; j++) {
			if (str[j] == '#')
				flag.push_back(-1);//代表不可行走
			if (str[j] == '+')
				flag.push_back(4);//代表可以走四个方向
			if (str[j] == '-')
				flag.push_back(3);//代表可以走左右
			if (str[j] == '|')
				flag.push_back(2);//上下
			if (str[j] == '.')
				flag.push_back(1);//下
			if (str[j] == 'S')
			{
				flag.push_back(4);
				s = i*colcount + j;//记录起点
			}
			if (str[j] == 'T')
			{
				flag.push_back(4);
				t = i*colcount + j;//记录终点
			}
		}
	}
	queue<int> qe;
	qe.push(s);
	vector<int> visited;//保存信息,如果能从起点走到当前点,则为1,否则为0
	for (int i = 0; i < rowcount; i++)
		for (int j = 0; j < colcount; j++)
			visited.push_back(0);
	while (!qe.empty()) {//广度优先遍历,用队列实现
		int m = qe.front();
		qe.pop();
		visited[m] = 1;
		//这里其实可以不加,挪到循环外面就行(保证起点是可以从起点到达的)
		//因为每一次将没有被访问过的点加入队列时,已经将visited置为1
		if (flag[m] == 4) {//分别处理可以走的方向
			int im = m / colcount;
			int jm = m %colcount;
			if (jm - 1 >= 0 && flag[m - 1] != -1&&visited[m-1]==0) {
				visited[m - 1] = 1;
				qe.push(m - 1);
				
			}
			if (jm + 1 < colcount&&flag[m + 1] != -1 && visited[m + 1] == 0) {
				visited[m + 1] = 1;
				qe.push(m + 1);
			}
			if (im - 1 >= 0 && flag[m - colcount] != -1 && visited[m - colcount] == 0) {
				visited[m - colcount] = 1;
				qe.push(m - colcount);
			}
			if (im + 1 < rowcount&&flag[m + colcount] != -1 && visited[m + colcount] == 0) {
				visited[m +colcount] = 1;
				qe.push(m + colcount);
			}
		}
		if (flag[m] == 3) {
			int jm = m %colcount;
			if (jm - 1 >= 0 && flag[m - 1] != -1 && visited[m - 1] == 0) {
				visited[m - 1] = 1;
				qe.push(m - 1);
			}
			if (jm + 1 < colcount&&flag[m + 1] != -1 && visited[m + 1] == 0) {
				visited[m + 1] = 1;
				qe.push(m + 1);
			}
		}
		if (flag[m] == 2) {
			int im = m / colcount;
			if (im - 1 >= 0 && flag[m - colcount] != -1 && visited[m - colcount] == 0) {
				visited[m - colcount] = 1;
				qe.push(m - colcount);
			}
			if (im + 1 < rowcount&&flag[m + colcount] != -1 && visited[m + colcount] == 0) {
				visited[m + colcount] = 1;
				qe.push(m + colcount);
			}
		}
		if (flag[m] == 1) {
			int im = m / colcount;
			if (im + 1 < rowcount&&flag[m + colcount] != -1 && visited[m + colcount] == 0) {
				visited[m + colcount] = 1;
				qe.push(m + colcount);
			}
		}
	}
	int num = 0;
	vector<int> index;//记录可以到达终点T的点,可以到达置为1
	for (int i = 0; i < rowcount; i++)
		for (int j = 0; j < colcount; j++)
			index.push_back(0);
	if (visited[t] != 0) {//起点可以到达终点
		index[s] = 1;
		index[t] = 1;
		vector<int> vec;
		for (int i = 0; i < rowcount; i++)
			for (int j = 0; j < colcount; j++)
				vec.push_back(0);//新的“visited”数组,用于判断k是否到达终点
		for (int k = 0; k < rowcount*colcount; k++){
			if (visited[k] == 0) {//那些起点不可以到达的点,不考虑
				continue;
			}
			if (k == s||k==t) {//起点和终点,不考虑
				continue;
			}
			num++;//假设该点不可到达
			setALL(vec, 0);//vec设置为全0
			qe.push(k);
			while (!qe.empty()) {//和之前的广度优先遍历差不多,只是从k开始
				int m = qe.front();
				qe.pop();
				vec[m] = 1;
				if (index[m] == 1) {//如果该点可以到达的点m已经被证明可到达终点,不再判断
					num--;
					index[k] = 1;
					break;
				}
				if (flag[m] == 4) {
					int im = m / colcount;
					int jm = m %colcount;
					if (jm - 1 >= 0 && flag[m - 1] != -1 && vec[m - 1] == 0) {
						vec[m - 1] = 1;
						qe.push(m - 1);
					}
					if (jm + 1 < colcount&&flag[m + 1] != -1 && vec[m + 1] == 0) {
						vec[m + 1] = 1;
						qe.push(m + 1);
					}
					if (im - 1 >= 0 && flag[m - colcount] != -1 && vec[m - colcount] == 0) {
						vec[m - colcount] = 1;
						qe.push(m - colcount);
					}
					if (im + 1 < rowcount&&flag[m + colcount] != -1 && vec[m + colcount] == 0) {
						vec[m + colcount] = 1;
						qe.push(m + colcount);
					}
				}
				if (flag[m] == 3) {
					int jm = m %colcount;
					if (jm - 1 >= 0 && flag[m - 1] != -1 && vec[m - 1] == 0) {
						vec[m - 1] = 1;
						qe.push(m - 1);
					}
					if (jm + 1 < colcount&&flag[m + 1] != -1 && vec[m + 1] == 0) {
						vec[m + 1] = 1;
						qe.push(m + 1);
					}
				}
				if (flag[m] == 2) {
					int im = m / colcount;
					if (im - 1 >= 0 && flag[m - colcount] != -1 && vec[m - colcount] == 0) {
						vec[m - colcount] = 1;
						qe.push(m - colcount);
					}
					if (im + 1 < rowcount&&flag[m + colcount] != -1 && vec[m + colcount] == 0) {
						vec[m + colcount] = 1;
						qe.push(m + colcount);
					}
				}
				if (flag[m] == 1) {
					int im = m / colcount;
					if (im + 1 < rowcount&&flag[m + colcount] != -1 && vec[m + colcount] == 0) {
						vec[m + colcount] = 1;
						qe.push(m + colcount);
					}
				}
				if (vec[t] != 0) {//如果m周围的店有终点,那么会在上面的方向处理中将其vec置为1
					num--;
					index[k] = 1;
					break;
				}
			}
			while (!qe.empty()) {//清空队列
				qe.pop();
			}
		}
		cout << num << endl;
	}
	else {
		cout << "I'm stuck!" << endl;
	}
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38941327/article/details/82872609