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;
	}
posted @ 2018-10-24 17:58  Tony_Double_Sky  阅读(242)  评论(0编辑  收藏  举报