算法思想:使用广度优先遍历(队列实现)
步骤: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;
}