CodeForces - 1520G To Go Or Not To Go?(bfs)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 1520G To Go Or Not To Go?(bfs)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:给出一个 n ∗ m n*m nm 的矩阵,其中:

  1. − 1 -1 1:该位置是个墙
  2. 0 0 0:该位置可以通过
  3. x ( x > 0 ) x(x>0) x(x>0):该位置是传送门

对于任意两个传送门,可以花费其权值和的代价相互到达

也可以花费 w w w 向上下左右四个方向移动

问从 ( 1 , 1 ) (1,1) (1,1) ( n , m ) (n,m) (n,m) 的最小花费是多少

题目分析:一开始想到了对传送门建一个超级源点,将所有传送门都与超级源点相连然后跑迪杰斯特拉,但是这样就有 1 e 7 1e7 1e7 条边,迪杰斯特拉又是超时又是内存超限

分析一下本题的性质,有一个比较重要的点就是,如果是走传送门的话,肯定只会从一个传送门进去然后从另一个传送门出来,因为假如传送门 A A A B B B 是可行的,那么肯定不会选择 A A A C C C,然后再从 C C C B B B

所以最小花费只有两种情况:

  1. ( 1 , 1 ) (1,1) (1,1) 不走传送门直接到 ( n , m ) (n,m) (n,m)
  2. ( 1 , 1 ) (1,1) (1,1) 到传送门 A A A ,传送到 B B B,然后从 B B B ( n , m ) (n,m) (n,m)

基于此,可以用 b f s bfs bfs 计算出所有点到 ( 1 , 1 ) (1,1) (1,1) 的距离和 ( n , m ) (n,m) (n,m) 的距离,然后枚举所有的传送门维护出 A A A B B B 即可

代码:

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
	T f=1;x=0;
	char ch=getchar();
	while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=f;
}
template<typename T>
inline void write(T x)
{
	if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const LL inf=0x3f3f3f3f3f3f3f3f;
const int N=2e3+100;
const int b[4][2]={0,1,0,-1,1,0,-1,0};
int n,m,w;
int maze[N][N];
LL d1[N][N],d2[N][N];
void bfs(int x,int y,LL d[][N]) {
	memset(d,-1,sizeof(LL)*(N*N));
	queue<pair<int,int>>q;
	q.push({x,y});
	d[x][y]=0;
	while(q.size()) {
		int x,y;
		tie(x,y)=q.front();
		q.pop();
		for(int i=0;i<4;i++) {
			int xx=x+b[i][0];
			int yy=y+b[i][1];
			if(xx<=0||xx>n||yy<=0||yy>m) {
				continue;
			}
			if(maze[xx][yy]==-1||d[xx][yy]!=-1) {
				continue;
			}
			d[xx][yy]=d[x][y]+w;
			q.push({xx,yy});
		}
	}
}
int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	read(n),read(m),read(w);
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			read(maze[i][j]);
		}
	}
	bfs(1,1,d1);
	bfs(n,m,d2);
	LL ans=inf;
	if(d1[n][m]!=-1) {
		ans=min(ans,d1[n][m]);
	}
	LL res1=inf,res2=inf;
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			if(maze[i][j]>0) {
				if(d1[i][j]!=-1) {
					res1=min(res1,d1[i][j]+maze[i][j]);
				}
				if(d2[i][j]!=-1) {
					res2=min(res2,d2[i][j]+maze[i][j]);
				}
			}
		}
	}
	ans=min(ans,res1+res2);
	if(ans==inf) {
		puts("-1");
		return 0;
	}
	write(ans);
    return 0;
}

以上是关于CodeForces - 1520G To Go Or Not To Go?(bfs)的主要内容,如果未能解决你的问题,请参考以下文章

codeforces 868A Bark to Unlock

Codeforces 868A Bark to Unlock

#3 Codeforces-865C Gotta Go Fast(期望dp)

go语言,window怎么实现常驻内存

codeforces 803B Distances to Zero

Codeforces 702 D Road to Post Office