您的位置:首页 > 其它

第十一届湖南省省赛 - 简单的图论问题?(BFS)

2015-09-01 16:47 323 查看


简单的图论问题?


题目描述

给一个 n 行 m 列的迷宫,每个格子要么是障碍物要么是空地。每个空地里都有一个权值。你的任务是从找一条(r1,c1)到(r2,c2)的路径,使得经过的空地的权值之和最小。每一步可以往上下左右四个方向之一移动一格,但不能斜着移动,也不能移动到迷宫外面或者进入障碍物格子。 如下图,灰色格子代表障碍物。路径 A->B->D->F->E 的权值为 10+3+6+14+8=41,它是从 A 到E 的最优路径。注意,如果同一个格子被经过两次,则权值也要加两次。                   
ABG
CDH
EF
71039
4562
814
211
为了让题目更有趣(顺便增加一下难度),你还需要回答另外一个问题:如果你每次必须转弯(左转、右转或者后退,只要不是沿着上次的方向继续走即可),最小权值是多少?比如,在上图中,如果你刚刚从 A 走到 B,那么下一步你可以走到 D 或者 A,但不能走到 G。在上图中,A 到 E 的最优路径是 A->B->D->H->D->F->E,权和为 10+3+6+2+6+14+8=49。注意,D 经过了两次。



输入描述

输入包含不超过10组数据。每组数据第一行包含6个整数n, m, r1, c1, r2, c2 (2<=n,m<=500, 1<=r1,r2<=n, 1<=c1,c2<=m). 接下来的n行每行包含m个格子的描述。每个格子要么是一个1~100的整数,要么是星号"*"(表示障碍物)。起点和终点保证不是障碍物。



输出描述

对于每组数据,输出两个整数。第一个整数是“正常问题”的答案,第二个整数是“有趣问题”的答案。如果每个问题的答案是“无解”,对应的答案应输出-1。



输入样例

4 4 1 2 3 2
7 10 3 9
* 45 6 2
* 8 14 *
21 1 * *
2 4 1 1 1 4
1 2 3 4
9 * * 9
2 4 1 1 1 4
1 * 3 4
9 9 * 9



输出样例

Case 1: 41 49
Case 2: 10 -1
Case 3: -1 -1这个题目纯粹水题,第一问大家都会,第二问只要简单的记录一下路径方向就可以了C++:
#include <map>
#include <set>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <iostream>
#include <string>
#include <sstream>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <algorithm>
using namespace std;

#define pb push_back
#define fillchar(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a))

typedef long long LL;
typedef pair<int, int > PII;
typedef unsigned long long uLL;
template<typename T>
void print(T* p, T* q, string Gap = " ") {
int d = p < q ? 1 : -1;
while(p != q) {
cout << *p;
p += d;
if(p != q) cout << Gap;
}
cout << endl;
}
template<typename T>
void print(const T &a, string bes = "") {
int len = bes.length();
if(len >= 2)cout << bes[0] << a << bes[1] << endl;
else cout << a << endl;
}

const int INF = 0x3f3f3f3f;
const int MAXM = 1e5;
const int MAXN = 5e2 + 5;
int n, m, r1, c1, step1, step2, r2, c2, mp[MAXN][MAXN];
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
bool vis[MAXN][MAXN],viss[MAXN][MAXN][4];
char op[5];

struct point{
int x, y, step, dist;
point(int x,int y,int step):x(x),y(y),step(step){}
point(int x,int y,int dist,int step):x(x),y(y),dist(dist),step(step){}
bool operator >(const point & a) const{
return step > a.step;
}
};

void BFS1(){
memset(vis, false, sizeof(vis));
priority_queue<point,vector<point>, greater<point> > que;
que.push(point(r1, c1, 0));
vis[r1][c1] = true;
while(!que.empty()){
point e = que.top();
que.pop();
if(e.x == r2 && e.y == c2) {
step1 = e.step;
return;
}
for(int i = 0;i < 4;i ++){
int nx = e.x + dx[i];
int ny = e.y + dy[i];
if(nx <= 0 || ny <= 0|| nx > n || ny > m || vis[nx][ny] || mp[nx][ny] == -1) continue;
vis[nx][ny] = true;
que.push(point(nx, ny, e.step + mp[nx][ny]));
}
}
}

void BFS2(){
memset(viss, false, sizeof(viss));
priority_queue<point,vector<point>, greater<point> > que;
que.push(point(r1, c1, 0, 0));
que.push(point(r1, c1, 1, 0));
que.push(point(r1, c1, 2, 0));
que.push(point(r1, c1, 3, 0));
viss[r1][c1][0] = viss[r1][c1][1] = viss[r1][c1][2] = viss[r1][c1][3] = true;
while(!que.empty()){
point e = que.top();
que.pop();
if(e.x == r2 && e.y == c2) {
step2 = e.step;
return;
}
for(int i = 0;i < 4;i ++){
if(i == e.dist) continue;
int nx = e.x + dx[i];
int ny = e.y + dy[i];
if(nx <= 0 || ny <= 0|| nx > n || ny > m || viss[nx][ny][i] || mp[nx][ny] == -1) continue;
viss[nx][ny][i] = true;
que.push(point(nx, ny, i, e.step + mp[nx][ny]));
}
}
}

int main(){
int cas = 1;
while(cin >> n >> m >> r1 >> c1 >> r2 >> c2){
step2 = step1 = -1;
for(int i = 1;i <= n;i ++){
for(int j = 1;j <= m;j ++){
cin >> op;
if(op[0] == '*'){
mp[i][j] = -1;
}
else{
mp[i][j] = atoi(op);
}
}
}
BFS1();
BFS2();
if(step1 != -1) step1 += mp[r1][c1];
if(step2 != -1) step2 += mp[r1][c1];
printf("Case %d: %d %d\n",cas ++, step1, step2);
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: