6286. 2019.08.09【NOIP提高组A】走格子

15 篇文章 0 订阅

Description

Input

Output

Sample Input

Sample 1:
4 4
####
#.F#
#C.#
####

Sample 2:
6 8
########
#.##..F#
#C.##..#
#..#...#
#.....##
########

Sample 3:
#####
#C#.#
###F#
#####
 

Sample Output

Sample 1:
2

Sample 2:
4

Sample 3:
no
 

Data Constraint

Hint

Solution

spfa。
将上下左右4个方的各向两种走法都连上边,之后跑一边spfa即可。
spfa大法好啊

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#define I int
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define N 502
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
I rd(){
	I x=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*w;
}
I n,m,sx,sy,tx,ty,tot,s[4*N*N],bz[N*N],u[N][N],d[N][N],l[N][N],r[N][N],f[N*N],g[N][N],fx[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
I ls[N*N],t[N*N*8],nx[N*N*8],v[N*N*8];
char ch,c[N][N];
I p(I x,I y){return (x-1)*m+y;}
void add(I x,I y,I z){
	t[++tot]=y;nx[tot]=ls[x];v[tot]=z;ls[x]=tot;
}
I main(){
	open("cell");
	n=rd();m=rd();
	F(i,1,n){
		F(j,1,m){
			ch=getchar();
			while(ch!='#'&&ch!='.'&&ch!='C'&&ch!='F') ch=getchar();
			c[i][j]=ch;
			if(ch=='C'){sx=i,sy=j;}
			if(ch=='F'){tx=i,ty=j;}
			if(ch=='#'){u[i][j]=d[i][j]=l[i][j]=r[i][j]=-1;}
		}
	}
	F(i,1,n)
		F(j,1,m)
			if(c[i][j]!='#'){
				u[i][j]=u[i-1][j]+1;
				l[i][j]=l[i][j-1]+1;
			}
	Fd(i,n,1)
		Fd(j,m,1)
			if(c[i][j]!='#'){
				d[i][j]=d[i+1][j]+1;
				r[i][j]=r[i][j+1]+1;
				g[i][j]=min(u[i][j],l[i][j]);
				g[i][j]=min(g[i][j],d[i][j]);
				g[i][j]=min(g[i][j],r[i][j]);
				g[i][j]++;
			}
	F(i,1,n){
		F(j,1,m){
			if(c[i][j]!='#'){
				F(k,0,3){
					I x=i+fx[k][0],y=j+fx[k][1];
					if(x>n||x<0||y<0||y>m||c[x][y]=='#') continue;
					add(p(i,j),p(x,y),1);
				}
				if(u[i][j]) add(p(i,j),p(i-u[i][j],j),g[i][j]);
				if(d[i][j]) add(p(i,j),p(i+d[i][j],j),g[i][j]);
				if(l[i][j]) add(p(i,j),p(i,j-l[i][j]),g[i][j]);
				if(r[i][j]) add(p(i,j),p(i,j+r[i][j]),g[i][j]);
			}
		}
	}
	mem(f,127);
	I i=1,j=1;s[1]=p(sx,sy);f[s[1]]=0;
	while(i<=j){
		I x=s[i++];bz[x]=0;
		for(I k=ls[x];k;k=nx[k]){
			if(f[t[k]]>f[x]+v[k]){
				f[t[k]]=f[x]+v[k];
				if(!bz[t[k]]){
					bz[t[k]]=1;
					s[++j]=t[k];
				}
			}
		}
	}
	if(f[p(tx,ty)]==f[0]) printf("no\n");
	else printf("%d\n",f[p(tx,ty)]);
	return 0;
}

作者:zsjzliziyang 
QQ:1634151125 
转载及修改请注明 
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/98997639

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值