Jzoj P6286 走格子___spfa

旧时模样 提交于 2019-11-26 17:12:02

题目大意:

在这里插入图片描述
在这里插入图片描述

分析:

对于每个点,
向四个相邻点连边,边权为1
向四个方向最远能走到的点连边,边权为通过其他三个方向的传送门走到这个点的最小值
spfa即可

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>

#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)

#define inf 0x7fffffff
#define N 505

using namespace std;

struct Node {
	int To, nxt, w;
}e[N*N*8*2];
struct Code {
	int up, down, lf, rt;
}C[N][N];
int id[N][N], a[N][N], dis[N*N], ls[N*N], S, T, n, m, cnt;
bool vis[N*N];

queue <int> Q;

void Addedge(int u, int v, int w) {
	if (u < 1 || u > n * m || v < 1 || v > n * m || u == v) return;
	e[++cnt].To = v, e[cnt].nxt = ls[u], e[cnt].w = w, ls[u] = cnt;
}

void spfa() {
    rep(i, 1, n * m) dis[i]	= inf;
    dis[S] = 0; vis[S] = 1; Q.push(S);
    while (Q.size()) {
    	int u = Q.front(); Q.pop();
    	for (int i = ls[u]; i; i = e[i].nxt) 
    		if (dis[e[i].To] > dis[u] + e[i].w) {
    			dis[e[i].To] = dis[u] + e[i].w;
    			if (!vis[e[i].To]) vis[e[i].To] = 1, Q.push(e[i].To);
    		}
    	vis[u] = 0;
    }
} 

int main() {
	freopen("cell.in", "r", stdin);
	freopen("cell.out", "w", stdout);
	scanf("%d %d", &n, &m);
	char ch[N];
	rep(i, 1, n) {
		scanf("%s", ch + 1); 
		rep(j, 1, m) {
			if (ch[j] != '#') a[i][j] = 1;
			id[i][j] = m * (i - 1) + j; 
			if (ch[j] == 'C') S = id[i][j];
			if (ch[j] == 'F') T = id[i][j];
		}
	}
	rep(i, 1, n) 
	   rep(j, 1, m) if (a[i][j]) C[i][j].up = C[i - 1][j].up + 1, C[i][j].lf = C[i][j - 1].lf + 1;
	rwp(i, n, 1) 
	   rwp(j, m, 1) if (a[i][j]) C[i][j].down = C[i + 1][j].down + 1, C[i][j].rt = C[i][j + 1].rt + 1;
	rep(i, 1, n) 
	   rep(j, 1, m) if (a[i][j]) {
	   	   Addedge(id[i][j], id[i - 1][j], 1); Addedge(id[i][j], id[i + 1][j], 1);
	   	   Addedge(id[i][j], id[i][j - 1], 1); Addedge(id[i][j], id[i][j + 1], 1);
	   	   Addedge(id[i][j], id[i - C[i][j].up + 1][j], min(C[i][j].down, min(C[i][j].lf, C[i][j].rt)));
	   	   Addedge(id[i][j], id[i + C[i][j].down - 1][j], min(C[i][j].up, min(C[i][j].lf, C[i][j].rt)));
	   	   Addedge(id[i][j], id[i][j - C[i][j].lf + 1], min(C[i][j].rt, min(C[i][j].up, C[i][j].down)));
	   	   Addedge(id[i][j], id[i][j + C[i][j].rt - 1], min(C[i][j].lf, min(C[i][j].up, C[i][j].down)));	   
	   }     
	spfa();
	if (dis[T] != inf) printf("%d\n", dis[T]); else printf("no\n");
	return 0;
} 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!