POJ 3026 Borg Maze BFS+最小生成树
2016-08-05 15:29
405 查看
按照我们学校训练计划从上往下刷,终于在许多人之后刷到了这个题。看完题目之后,思考了一会,认为是个BFS+最小生成树。虽然事实确实如此,但是,这个题有大坑!这个题有大坑!这个题有大坑!重要的事说三遍。对于一些同学,这些坑根本踩不着,但对于习惯另外一些写法的同学,这个题会让人WA到死。
首先看题意,说的是要使所有的S与A连接在一起,且总权值最低,这个就是要用BFS算出任意两点之间的距离,然后跑最小生成树就行,这里A和S并没有什么区别,全部按一样的处理就行。
然后我们来说坑,我WA的受不了了,去POJ的留言板上才发现的,首先,这个题说的输入会在50以内,其实开一百都会RE,我最后开了333;其次,这个题的数字输入后,会有一串的空格,那些习惯%*c或者getch消掉换行符的同学们就等着无限WA吧。这里我的做法是gets吃掉数字后面这一行的所有字符。只要避开了这两个坑,其实其他的也就没什么坑点了,直接上代码。
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
struct node
{
int x, y;
}a[55*55*55], now;
int top, base, Map[333][333], Book[333][333], edge[333][333], x, y;
struct nnode
{
int x, y, step;
}s[55*55*55], next;
int in(int n)
{
for (int i = 0; i < top; i++)
if (s
.x == a[i].x && s
.y == a[i].y)
return i;
return -1;
}
void BFS(int n)//BFS求任意两点之间的距离 是比较格式化的东西
{
const int dict[4][2] = {{-1, 0}, {1, 0},{0,-1},{0,1}};
memset(Book, 0, sizeof Book);
int Top = 0, Base = 0;
next.x = a
.x;
next.y = a
.y;
next.step = 0;
s[Top++] = next;
Book[a
.x][a
.y] = 1;
while (Base < Top)
{
if (Map[s[Base].x][s[Base].y] == -1)
edge
[in(Base)] = s[Base].step;
for (int i = 0; i < 4; i++)
{
next.x = s[Base].x + dict[i][0];
next.y = s[Base].y + dict[i][1];
next.step = s[Base].step + 1;
if (next.x >= 0 && next.y >= 0 && next.x < y && next.y < x)
if (!Book[next.x][next.y] && Map[next.x][next.y] != 1)
{
s[Top++] = next;
Book[next.x][next.y] = 1;
}
}
Base++;
}
}
int BBook[333], Min[333];
int Prim(int n)//Prim求最小生成树 基本就是个板子
{
int ans = 0;
for (int i = 0; i < n; i++)
Min[i] = edge[1][i];
memset(BBook, 0, sizeof BBook);
BBook[1] = 1;
for (int i = 0; i < n - 1; i++)
{
int pos, s = 23333333;
for (int j = 0; j < n; j++)
if (!BBook[j] && s > Min[j])
{
s = Min[j];
pos = j;
}
if (s == 23333333)
break;
BBook[pos] = 1;
ans += s;
for (int j = 0; j < n; j++)
if (!BBook[j] && Min[j] > edge[pos][j])
Min[j] = edge[pos][j];
}
return ans;
}
int main()
{
int T, i, j;
cin >> T;
while (T--)
{
top = base = 0;
cin >> x >> y;//这里之前无限WA的时候试了各种输入,然后忘了改回去了
char str[333];
gets(str);
for (i = 0; i < y; i++)
{
gets(str);
for (j = 0; j < x; j++)
{
if (str[j] == '#')
Map[i][j] = 1;
else if (str[j] == ' ')
Map[i][j] = 0;
else if (str[j] == 'A' || str[j] == 'S')
{
Map[i][j] = -1;
now.x = i;
now.y = j;
a[top++] = now;
}
}
}
for (i = 0; i < top; i++)
{
BFS(i);
}
// for (i = 0; i < top; i++)
// {
// for (j = 0; j < top; j++)
// printf("%d ", edge[i][j]);
// printf("\n");
// }
printf("%d\n", Prim(top));
}
return 0;
}
首先看题意,说的是要使所有的S与A连接在一起,且总权值最低,这个就是要用BFS算出任意两点之间的距离,然后跑最小生成树就行,这里A和S并没有什么区别,全部按一样的处理就行。
然后我们来说坑,我WA的受不了了,去POJ的留言板上才发现的,首先,这个题说的输入会在50以内,其实开一百都会RE,我最后开了333;其次,这个题的数字输入后,会有一串的空格,那些习惯%*c或者getch消掉换行符的同学们就等着无限WA吧。这里我的做法是gets吃掉数字后面这一行的所有字符。只要避开了这两个坑,其实其他的也就没什么坑点了,直接上代码。
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
struct node
{
int x, y;
}a[55*55*55], now;
int top, base, Map[333][333], Book[333][333], edge[333][333], x, y;
struct nnode
{
int x, y, step;
}s[55*55*55], next;
int in(int n)
{
for (int i = 0; i < top; i++)
if (s
.x == a[i].x && s
.y == a[i].y)
return i;
return -1;
}
void BFS(int n)//BFS求任意两点之间的距离 是比较格式化的东西
{
const int dict[4][2] = {{-1, 0}, {1, 0},{0,-1},{0,1}};
memset(Book, 0, sizeof Book);
int Top = 0, Base = 0;
next.x = a
.x;
next.y = a
.y;
next.step = 0;
s[Top++] = next;
Book[a
.x][a
.y] = 1;
while (Base < Top)
{
if (Map[s[Base].x][s[Base].y] == -1)
edge
[in(Base)] = s[Base].step;
for (int i = 0; i < 4; i++)
{
next.x = s[Base].x + dict[i][0];
next.y = s[Base].y + dict[i][1];
next.step = s[Base].step + 1;
if (next.x >= 0 && next.y >= 0 && next.x < y && next.y < x)
if (!Book[next.x][next.y] && Map[next.x][next.y] != 1)
{
s[Top++] = next;
Book[next.x][next.y] = 1;
}
}
Base++;
}
}
int BBook[333], Min[333];
int Prim(int n)//Prim求最小生成树 基本就是个板子
{
int ans = 0;
for (int i = 0; i < n; i++)
Min[i] = edge[1][i];
memset(BBook, 0, sizeof BBook);
BBook[1] = 1;
for (int i = 0; i < n - 1; i++)
{
int pos, s = 23333333;
for (int j = 0; j < n; j++)
if (!BBook[j] && s > Min[j])
{
s = Min[j];
pos = j;
}
if (s == 23333333)
break;
BBook[pos] = 1;
ans += s;
for (int j = 0; j < n; j++)
if (!BBook[j] && Min[j] > edge[pos][j])
Min[j] = edge[pos][j];
}
return ans;
}
int main()
{
int T, i, j;
cin >> T;
while (T--)
{
top = base = 0;
cin >> x >> y;//这里之前无限WA的时候试了各种输入,然后忘了改回去了
char str[333];
gets(str);
for (i = 0; i < y; i++)
{
gets(str);
for (j = 0; j < x; j++)
{
if (str[j] == '#')
Map[i][j] = 1;
else if (str[j] == ' ')
Map[i][j] = 0;
else if (str[j] == 'A' || str[j] == 'S')
{
Map[i][j] = -1;
now.x = i;
now.y = j;
a[top++] = now;
}
}
}
for (i = 0; i < top; i++)
{
BFS(i);
}
// for (i = 0; i < top; i++)
// {
// for (j = 0; j < top; j++)
// printf("%d ", edge[i][j]);
// printf("\n");
// }
printf("%d\n", Prim(top));
}
return 0;
}
相关文章推荐
- Android Retrofit RxJava实现缓存
- jQuery 提供多个与 AJAX 有关的方法。
- HDU 5793 A Boring Question
- 企业自研扫描器之路:信息收集模块
- kafka环境搭建及librdkafka测试
- kmp 算法演示
- Monkey测试简介[附示例]
- Bootstrap 3 布局
- Android BLE蓝牙4.0开发详解
- Jquery的单选框选中
- in与exists
- bindService失败的解决办法
- Python中的打开文件对话框
- vxWorks下,telnet客户端以及pty设备驱动
- 【leetcode】Insert Delete GetRandom O(1)
- #ifdef __cplusplus extern "C" { #endif //一段代码 #ifdef __cplusplus } #endif
- SE新手游操控创新:一个按键=五个技能
- ios时间戳13位转换
- 第三方集成的坑如:java.util.zip.ZipException: duplicate entry: com/ta/utdid2/android/utils/AESUtils.class
- C++11 thread_local 关键词