简单的图论问题?

简单的图论问题?
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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值