题目见http://bailian.openjudge.cn/practice/1101/ ,此处仅分析思路
一、WA的代码
初看以为是简单的宽搜,WA了一下午,WA代码也贴一下好了
#include <iostream>
#include <iomanip>
#include <queue>
using namespace std;
char a[80][80];
int vis[80][80];
int w, h;
int xx[4] = { 0, -1, 0, 1 }; //左 上 右 下
int yy[4] = { -1, 0, 1, 0 };
struct Node {
int x;
int y;
int step;
int count;
};
bool is_in(int x, int y) {
return (x >= 0 && x <= h + 1 && y >= 0 && y <= w + 1);
}
int bfs(int x1, int y1, int x2, int y2) {
int count = -1;
queue<Node*> qu;
Node* node = new Node;
node->x = x1;
node->y = y1;
node->step = -1;
node->count = 0;
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
vis[i][j] = 0;
}
}
vis[x1][y1] = 1;
qu.push(node);
while (qu.empty() != true) {
node = qu.front();
qu.pop();
if (node->x == x2 && node->y == y2) {
if (count == -1 || count > node->count)
count = node->count;
continue;
}
if (node->count > count && count != -1) continue;
for (int i = 0; i < 4; i++) {
int x = node->x + xx[i];
int y = node->y + yy[i];
Node* temp = new Node;
temp->x = x;
temp->y = y;
temp->step = i;
if (i != node->step)
temp->count = node->count + 1;
else
temp->count = node->count;
if ((is_in(x, y) && a[x][y] == ' ' && vis[x][y] == 0) || (x == x2 && y == y2)) {
// << " " << x << " wsd " << y << endl;
qu.push(temp);
vis[x][y] = 1;
}
}
}
return count;
}
int main() {
int sum = 0;
while (cin >> w >> h) {
cin.get();
if (w == 0 && h == 0) break;
sum++;
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
a[i][j] = ' ';
}
}
for (int i = 1; i <= h; i++) {
cin.getline(a[i], w + 1);
for (int j = w; j >= 0; j--) {
a[i][j] = a[i][j - 1];
}
a[i][0] = ' ';
}
int x1, y1, x2, y2;
int num = 0;
cout << "Board #" << sum << ":" << endl;
while (cin >> x1 >> y1 >> x2 >> y2) {
num++;
if (x1 == 0 && y1 == 0 && x2 == 0 && y2 == 0) break;
cout << "Pair " << num << ": ";
int temp = bfs(y1, x1, y2, x2);
if (temp == -1)
cout << "impossible." << endl;
else {
cout << temp << " segments." << endl;
}
}
cout << endl;
}
//system("pause");
return 0;
}
二、AC了但其实是错误的代码
仅修改了宽搜顺序,也就是将上面代码第9行int xx[4] = { 0, -1, 0, 1 };
修改为int xx[4] = { 0, 1, 0, -1 };
就AC了,这是这题测试样例的 bug了
三、正确的AC代码
仔细一想,这题不是简单的宽搜,因为一格一格的走的话不能保证拐弯数是递增的,所以,这里的宽搜对象不应该是每一格,而应该是每一个方向。每次将同一方向上的所有格子加入队列中,然后换另一个方向,这样能保证拐弯数是递增的。
#include <iostream>
#include <iomanip>
#include <queue>
using namespace std;
char a[80][80];
int vis[80][80];
int w, h;
int xx[4] = { 0, 1, 0, -1 }; //左 上 右 下
int yy[4] = { -1, 0, 1, 0 };
struct Node {
int x;
int y;
int step;
int count;
};
bool is_in(int x, int y) {
return (x >= 0 && x <= h + 1 && y >= 0 && y <= w + 1);
}
int bfs(int x1, int y1, int x2, int y2) {
queue<Node*> qu;
Node* node = new Node;
node->x = x1;
node->y = y1;
node->step = -1;
node->count = 0;
vis[x1][y1] = 1;
qu.push(node);
while (qu.empty() != true) {
node = qu.front();
qu.pop();
for (int i = 0; i < 4; i++) {
if (i == node->step) continue;
int x = node->x + xx[i];
int y = node->y + yy[i];
while (is_in(x, y) && a[x][y] == ' '&& vis[x][y] == 0){
vis[x][y] = 1;
Node* temp = new Node;
temp->x = x;
temp->y = y;
temp->step = i;
temp->count = node->count + 1;
qu.push(temp);
x = x + xx[i];
y = y + yy[i];
}
if (x == x2 && y == y2) {
return node->count + 1;
}
}
}
return -1;
}
int main() {
int sum = 0;
while (cin >> w >> h) {
cin.get();
if (w == 0 && h == 0) break;
sum++;
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
a[i][j] = ' ';
}
}
for (int i = 1; i <= h; i++) {
cin.getline(a[i], w + 1);
for (int j = w; j >= 0; j--) {
a[i][j] = a[i][j - 1];
}
a[i][0] = ' ';
}
int x1, y1, x2, y2;
int num = 0;
cout << "Board #" << sum << ":" << endl;
while (cin >> x1 >> y1 >> x2 >> y2) {
num++;
if (x1 == 0 && y1 == 0 && x2 == 0 && y2 == 0) break;
cout << "Pair " << num << ": ";
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
vis[i][j] = 0;
}
}
int temp = bfs(y1, x1, y2, x2);
if (temp == -1)
cout << "impossible." << endl;
else {
cout << temp << " segments." << endl;
}
}
cout << endl;
}
//system("pause");
return 0;
}
最后的最后,啊,哭,我的一下午TAT