简单的图论问题?
Time Limit: 5000MS Memory Limit: 65535KB 64bit IO Format:
Submit
Status
Description
给一个 n 行 m 列的迷宫,每个格子要么是障碍物要么是空地。每个空地里都有一个权值。你的 任务是从找一条(r1,c1)到(r2,c2)的路径,使得经过的空地的权值之和最小。每一步可以往上下 左右四个方向之一移动一格,但不能斜着移动,也不能移动到迷宫外面或者进入障碍物格子。
如下图,灰色格子代表障碍物。路径 A->B->D->F->E 的权值为 10+3+6+14+8=41,它是从 A 到 E 的最优路径。注意,如果同一个格子被经过两次,则权值也要加两次。
为了让题目更有趣(顺便增加一下难度),你还需要回答另外一个问题:如果你每次必须转弯 (左转、右转或者后退,只要不是沿着上次的方向继续走即可),最小权值是多少?比如,在 上图中,如果你刚刚从 A 走到 B,那么下一步你可以走到 D 或者 A,但不能走到 G。在上图 中,A 到 E 的最优路径是 A->B->D->H->D->F->E,权和为 10+3+6+2+6+14+8=49。注意,D 经 过了两次。
Input
输入包含不超过 10 组数据。每组数据第一行包含 6 个整数 n, m, r1, c1, r2, c2 (2<=n,m<=500, 1<=r1,r2<=n, 1<=c1,c2<=m). 接下来的 n 行每行包含 m 个格子的描述。每个格子要么是一个 1~100 的整数,要么是星号”*”(表示障碍物)。起点和终点保证不是障碍物。
Output
对于每组数据,输出两个整数。第一个整数是“正常问题”的答案,第二个整数是“有趣问 题”的答案。如果每个问题的答案是“无解”,对应的答案应输出-1。
Sample Input
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
Sample Output
Case 1: 41 49
Case 2: 10 -1
Case 3: -1 -1
两个走法,用两个广搜,优先队列
注意特殊走法的标记就行了,“不能一直同一个方向”
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <set>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (10000+10)
#define MAXM (300000+10)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while((a)--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
#define N 501
using namespace std;
int vist[N][N],map[N][N];
int used[N][N][4];
int n,m;
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int ans1,ans2;
int check(int x,int y)
{
return x >= 0 && x < n && y >= 0 && y < m;
}
struct node{
int x, y, step, sum;
friend bool operator < (node a, node b){
return a.sum > b.sum;
}
};
void bfs1(int sx,int sy,int ex,int ey,int val)
{
node st,ed;
priority_queue<node>Q;
st.x=sx,st.y=sy,st.sum=val;
Q.push(st);
while(!Q.empty())
{
st=Q.top();
Q.pop();
if(st.x==ex&&st.y==ey)
{
ans1=st.sum;
return ;
}
for(int i=0;i<4;i++)
{
if(i==st.step)continue;
int nx=st.x+dir[i][0];
int ny=st.y+dir[i][1];
if(!check(nx,ny)||map[nx][ny]==-1||vist[nx][ny])
continue;
ed.x=nx,ed.y=ny,ed.sum=st.sum+map[nx][ny];
Q.push(ed);
vist[nx][ny]=1;
}
}
}
void bfs2(int sx,int sy,int ex,int ey,int step,int val)
{
node st,ed;
priority_queue<node>Q;
st.x=sx,st.y=sy,st.sum=val,st.step=-1;
Q.push(st);
while(!Q.empty())
{
st=Q.top();
Q.pop();
if(st.x==ex&&st.y==ey)
{
ans2=st.sum;
return ;
}
for(int i=0;i<4;i++)
{
if(i==st.step)continue;
int nx=st.x+dir[i][0];
int ny=st.y+dir[i][1];
if(!check(nx,ny)||map[nx][ny]==-1||used[st.x][st.y][i])
continue;
ed.x=nx,ed.y=ny,ed.sum=st.sum+map[nx][ny];
ed.step=i;
Q.push(ed);
used[st.x][st.y][i]=1;
}
}
}
int main()
{
int c= 1, x1, y1, x2, y2;
while(scanf("%d%d%d%d%d%d", &n, &m, &x1, &y1, &x2, &y2) != EOF)
{
x1--, y1--, x2--, y2--;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
char str[10]; Rs(str);
if(str[0] == '*') {map[i][j]= -1; continue;}
int len = strlen(str);
int val = 0;
for(int k = 0; k < len; k++)
val = val * 10 + (str[k] - '0');
map[i][j] = val;
}
}
ans1 = ans2 = INF; CLR(vist, false); vist[x1][y1] = true;
bfs1(x1, y1, x2, y2, map[x1][y1]);
CLR(used, false);
bfs2(x1, y1, x2, y2, -1, map[x1][y1]);
if(ans1 == INF) ans1 = -1;
if(ans2 == INF) ans2 = -1;
cout<<"Case "<<c++<<": "<<ans1<<' '<<ans2<<endl;
}
return 0;
}