Aizu - 0558 多源bfs
题目
在H * W的地图上有N个奶酪工厂,每个工厂分别生产硬度为1~N的奶酪。有一只老鼠准备从出发点吃遍每一个工厂的奶酪。老鼠有一个体力值,初始时为1,每吃一个工厂的奶酪体力值增加1(每个工厂只能吃一次),且老鼠只能吃硬度不大于当前体力值的奶酪。 老鼠从当前格到上下左右相邻的无障碍物的格需要时间1单位,有障碍物的格不能走。走到工厂上时即可吃到该工厂的奶酪,吃奶酪时间不计。问吃遍所有奶酪最少用时
输入
第一行三个整数H(1 <= H <= 1000)、W(1 <= W <=1000)、N(1 <= N <= 9),之后H行W列为地图, “.“为空地, ”X“为障碍物,”S“为老鼠洞,N表示有N个生产奶酪的工厂,硬度为1-N。
输出
输出一个整数,代表老鼠吃遍所有奶酪的最少时间花费。
样例
输入样例1
3 3 1
S..
...
..1
输出样例1
4
输入样例2
4 5 2
.X..1
....X
.XX.S
.2.X.
输出样例2
12
输入样例3
10 10 9
.X...X.S.X
6..5X..X1X
...XXXX..X
X..9X...X.
8.X2X..X3X
...XX.X4..
XX....7X..
X..X..XX..
X...X.XX..
..X.......
输出样例3
91
分析
从起点开始对下一个工厂做bfs,每bfs一次将最后这个工厂的位置改为'.',并将起点改为当前工厂的点,
因此输入的时候就要将这n个工厂存入结构体数组
代码
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstdlib>
using namespace std;
struct point {//用来存点的信息的结构体
int x;
int y;
char c;
};
int h, w, n;
char inp[1002][1002];//输入地图用的
int map[1002][1002];
char nub[12] = "0123456789";//用来把数字转换成字符串,这样nub[n]就是n对应的字符
struct point bfs(struct point s, struct point a);
void show() {//用于展示当前地图状态用于检查老鼠的移动
printf("\n");
int i, j;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
if (map[i][j] == -1) {
printf("%c", inp[i][j]);
} else {
printf("@");
}
}
printf("\n");
}
}
struct point aim[12];
void show_aim(int n) {//输出当前的目标
int i;
for (i = 1; i <= n; i++) {
printf("%d %d %c\n", aim[i].x, aim[i].y, aim[i].c);
}
}
bool jgsz(struct point n) {//判断该字符是不是一个数字
if (inp[n.x][n.y] >= '0' && inp[n.x][n.y] <= '9') {
return true;
} else {
return false;
}
}
bool jg(struct point n, struct point a) {//判断这个点是否符合bfs的要求
if (n.x > -1 && n.x < h && n.y > -1 && n.y < w && (map[n.x][n.y] == -1) && (inp[n.x][n.y] == '.'
|| jgsz(n) ) ) {
return true;
} else {
return false;
}
}
int main() {
//printf("%c %d\n", nub[2], nub[2]);//测试一下整整型和字符的转换
scanf("%d %d %d", &h, &w, &n);//读入第一行的三个数
if (h == 1 && w == 1) {
printf("0\n");
return 0;
}
getchar();
struct point s;//用来存起点的结构体
int sum = 0; //步数容器
int i, j, k;
for (i = 0; i <= n; i++) {
aim[i].c = i + '0';
}
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
scanf("%c", &inp[i][j]);
// printf("i%dj%d\n", i, j);//test
if (inp[i][j] == 'S') {//存入起点
s.x = i;
s.y = j;
s.c = 'S';
}
for (k = 1; k < 10; k++) {
if (inp[i][j] == aim[k].c) {
aim[k].x = i;
aim[k].y = j;
}
}
}
getchar();
}
//show();
//show_aim(n);
sum = 0;
for (k = 1; k <= n; k++) {
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
map[i][j] = -1;
}
}
inp[s.x][s.y]='.';//在bfs之前将起点改为'.'(即可通过状态)
struct point ans = bfs(s, aim[k]);
s.x = ans.x;
s.y = ans.y;
//printf("<==no:%d step:%d\n", k, map[s.x][s.y]);
sum += map[s.x][s.y];
}
printf("%d\n", sum);
}
struct point bfs(struct point s, struct point a) {
struct point n;
struct point nw;
queue<point> q;
q.push(s);
map[s.x][s.y] = 0;
while (!q.empty()) {
// printf("!!\n");
n = q.front();
q.pop();
if (inp[n.x][n.y] == a.c) {
//inp[n.x][n.y] = 'N';
//show();
inp[n.x][n.y] = '.';
break;
}
nw.x = n.x;
nw.y = n.y + 1;
if (jg(nw, a)) {
q.push(nw);
// show();
map[nw.x][nw.y] = map[n.x][n.y] + 1;
// printf("==>%d\n", map[nw.x][nw.y]);
}
nw.x = n.x;
nw.y = n.y - 1;
if (jg(nw, a)) {
q.push(nw);
// show();
map[nw.x][nw.y] = map[n.x][n.y] + 1;
// printf("==>%d\n", map[nw.x][nw.y]);
}
nw.x = n.x + 1;
nw.y = n.y;
if (jg(nw, a)) {
q.push(nw);
// show();
map[nw.x][nw.y] = map[n.x][n.y] + 1;
// printf("==>%d\n", map[nw.x][nw.y]);
}
nw.x = n.x - 1;
nw.y = n.y;
if (jg(nw, a)) {
q.push(nw);
//show();
map[nw.x][nw.y] = map[n.x][n.y] + 1;
//printf("==>%d\n", map[nw.x][nw.y]);
}
}
return n;
}
反思
最开始没有注意到“体力”的设定,直接对所有数字进行了bfs,导致最后输出不正确
后来没有修改起点为'.',导致总是wa一个点
估计是长这样的一个输入
输入
3 5 2
X2X
X.X
XSX
X.X
X1X
这样如果没有把起点改成'.'的话,bfs完第一个之后走不到第二个会报WA

浙公网安备 33010602011771号