算法思想:使用广度优先遍历(队列实现)
步骤: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,否则为0for (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置为1if (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的点,可以到达置为1for (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设置为全0qe.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置为1num--;index[k] = 1;break;}}while (!qe.empty()) {//清空队列qe.pop();}}cout << num << endl;}else {cout << "I'm stuck!" << endl;}system("pause");return 0;
}