P1649 [USACO07OCT]障碍路线Obstacle Course

P1649 [USACO07OCT]障碍路线Obstacle Course

N*N(1<=N<=100)方格中,’x’表示不能行走的格子,’.’表示可以行走的格子。卡门很胖,故而不好转弯。现在要从A点走到B点,请问最少要转90度弯几次?


调试日志: 左移写成右移了QAQ


Solution

正解应该是 \(bfs\) 吧, 每个状态保存 坐标, 步数, 方向, 搜索即可
偏不想正解, 哼
众所周知, 肥宅不可能来回踱步
因为 这样多了两步转向显然不优, 在前一步换个方向到只用一步
所以每个点分裂成两个点, 一个横向的一个纵向的
横向点之间连边, 权值为 \(0\) , 代表不需要转向
纵向点之间连边, 权值为 \(0\) , 代表不需要转向
自己的横向点到纵向点连边, 权值为 \(1\) , 代表转个向花费一
起点可以自由选择横向, 纵向, 到终点时状态横向纵向皆可
所以初始把横纵两种状态作为起始点, 最后看终点横纵状态那个最短路长度小即可

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define LL long long
#define REP(i, x, y) for(int i = (x);i <= (y);i++)
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 100019,INF = 1e9 + 19;
int head[maxn],nume = 1;
struct Node{
    int v,dis,nxt;
    }E[maxn << 3];
void add(int u,int v,int dis){
    E[++nume].nxt = head[u];
    E[nume].v = v;
    E[nume].dis = dis;
    head[u] = nume;
    }
int len;
int map[119][119], s, t;
int mx[4] = {0, 0, 1,-1};
int my[4] = {1,-1, 0, 0};
int id(int x, int y){return (x - 1) * len + y;}
bool judge(int x, int y){
    if(x < 1 || x > len || y < 1 || y > len)return 0;
    return 1;
    }
int d[maxn];
bool inq[maxn];
void SPFA(){
    queue<int>Q;
    d[s << 1] = d[s << 1 | 1] = 0;
    Q.push(s << 1), Q.push(s << 1 | 1);
    inq[s << 1] = inq[s << 1 | 1] = 1;
    while(!Q.empty()){
        int u = Q.front();Q.pop();inq[u] = 0;
        for(int i = head[u];i;i = E[i].nxt){
            int v = E[i].v, dis = E[i].dis;
            if(d[u] + dis < d[v]){
                d[v] = d[u] + dis;
                if(!inq[v])Q.push(v), inq[v] = 1;
                }
            }
        }
    }
int main(){
    len = RD();
    REP(i, 1, len)REP(j, 1, len){
        int now = id(i, j);
        d[now << 1] = d[now << 1 | 1] = INF;
        char ss[19];
        scanf("%s", ss);
        if(ss[0] == '.')map[i][j] = 1;
        else if(ss[0] == 'A')map[i][j] = 1, s = now;
        else if(ss[0] == 'B')map[i][j] = 1, t = now;
        }
    REP(i, 1, len)REP(j, 1, len){
        if(!map[i][j])continue;
        int u = id(i, j);
        add(u << 1, u << 1 | 1, 1);
        add(u << 1 | 1, u << 1, 1);
        REP(k, 0, 1){
            int nx = i + mx[k], ny = j + my[k];
            if(!judge(nx, ny) || !map[nx][ny])continue;
            int v = id(nx, ny);
            add(u << 1, v << 1, 0);
            }
        REP(k, 2, 3){
            int nx = i + mx[k], ny = j + my[k];
            if(!judge(nx, ny) || !map[nx][ny])continue;
            int v = id(nx, ny);
            add(u << 1 | 1, v << 1 | 1, 0);
            }
        }
    SPFA();
    int ans = min(d[t << 1], d[t << 1 | 1]);
    if(ans == INF){puts("-1");return 0;}
    printf("%d\n", ans);
    return 0;
    }

猜你喜欢

转载自www.cnblogs.com/Tony-Double-Sky/p/9844991.html
今日推荐