NOIP2013華容

免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/weixin_42557561/article/details/102732616
分析

好適タイトルサーチ取得した後
、暴力を70〜80人です
、私は唯一の5分を持っていますか?
DFSをハングアップする場所を私は知りません

BFSが考えるようになったとして
、死のサイクルの恐れので捨てられたタグを再生する方法を知っていない
問題の神々の解のターンの後、私は実現
重要な特性があるBFS、ノードへの最初の訪問は、そのから一定の最小距離に達する
バックをその後、優れた、そしてこれだけではなく、剪定のためにではないに到達するだけでなく、行くために事態を繰り返さないために
グリッド位置と4次元の現在の状態のために指定されたメモリと少し似て(何をすることができます保存する場所を今の位置であると便利の)

ポジティブなソリューション:
何を聞いて、同じ時間でのqを考えてみましょう。
ボードが変化し、グリッドを移動することが可能に指定するつもりはないので、場合にのみ、空白グリッドもしこれでアップ/ダウン/左/右。そして、私たちは事前にアウトすることができ、指定されたグリッドとして、各グリッドのその4つの方向のグリッドの空白状態が
状態と状態との関係を確立するために
、具体的:
グリッドの下に指定され、現在のスペースを、それが国家のために想定されます F [ バツ ] [ y ] [ 2 ] F [X] [Y] [2]
今指定空間左グリッドに転送される、すなわち、 f [ x ] [ y ] [ 3 ] F [X] [Y] [3]
f [ x ] [ y ] [ 3 ] = f [ x ] [ y ] [ 2 ] + s t e p F [X] [Y] [3] Fを= [X] [Y] [2] +ステップ
必要とBFSによって決定することができるステップの最小数

この処理後の状態が出て、それぞれの状態、マップ構築のために番号が付けられている
と最短を実行しました
。具体的:
により指定された場所に、指定したグリッドスペースは、最初は隣接していないことがあり
、我々は最初のでしょうBFSスペースの場所にそれを行う必要がありますグリッドを指定した四方向の移動(最終的な答えが、ターゲットグリッドの4つの方向にグリッドを指定してもよいしながら四点にソース側の等価物も、同じように動作することができます)

複雑分析,,
ない,,

コード
#include<bits/stdc++.h>
#define in read()
#define re register
using namespace std;
inline int read(){
	char ch;int f=1,res=0;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
	while(ch>='0'&&ch<='9'){
		res=(res<<1)+(res<<3)+(ch^48);
		ch=getchar();
	}
	return f==1?res:-res;
}
const int  N=35;
int n,m,q;
int a[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int f[N][N];
const int M=4009;
int nxt[M<<4],head[M],to[M<<4],w[M<<4],ecnt=0;
int dis[M<<2];
inline void add(int x,int y,int z){
//	printf("u=%d v=%d val=%d\n",x,y,z);
	nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;w[ecnt]=z;
}
inline int get_num(int x,int y){
	y--;
	return (x-1)*m+y<<2;
}
#define mp make_pair
void BFS(int ex,int ey,int px,int py,int d){
//	printf("px=%d py=%d ex=%d ey=%d\n",px,py,ex,ey);
	memset(f,-1,sizeof(f));
	f[ex][ey]=0;
	f[px][py]=1;
	queue<pair<int,int> > q;
	q.push(mp(ex,ey));
	while(!q.empty()){//预处理出来空格位置到其他位置的最短步数 
		int x=q.front().first,y=q.front().second;q.pop();
		for(re int i=0;i<4;++i){
			int xx=x+dx[i];
			int yy=y+dy[i];
			if(f[xx][yy]!=-1) continue;
			if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&a[xx][yy]){
				f[xx][yy]=f[x][y]+1;
				q.push(mp(xx,yy));
			}
		}
	}
	if(d==-1) return;
	int num=get_num(px,py);
//	printf("px=%d py=%d num=%d\n",px,py,num);
	for(re int i=0;i<4;++i){//状态转移 
		int x=px+dx[i];
		int y=py+dy[i];
//		x>=1&&x<=n&&y>=1&&y<=m&&
		if(f[x][y]>0)
			add(num+d,num+i,f[x][y]);
	}
	add(num+d,get_num(ex,ey)+(d+2)%4,1);
}
int INF;
bool vis[M<<2];
void spfa(int sx,int sy){
	queue<int> q;
	memset(vis,0,sizeof(vis));
	memset(dis,127/3,sizeof(dis));
	INF=dis[0];
	for(re int i=0;i<4;++i){
		int x=sx+dx[i];
		int y=sy+dy[i];
		if(x>=1&&x<=n&&y>=1&&y<=m&&f[x][y]!=-1){
			int num=get_num(sx,sy)+i;
			dis[num]=f[x][y];
			q.push(num);
//			printf("tmp=%d dis=%d\n",num,dis[num]);
		} 
	}
	while(!q.empty()){
		int u=q.front();q.pop();
		vis[u]=0;
		for(re int e=head[u];e;e=nxt[e]){
			int v=to[e];
			if(dis[v]>dis[u]+w[e]){
				dis[v]=dis[u]+w[e];
				if(vis[v]) continue;
				vis[v]=1;
				q.push(v);
			}
		}
	}
}
int main(){
	n=in;m=in;q=in;
	for(re int i=1;i<=n;++i)
		for(re int j=1;j<=m;++j)
			a[i][j]=in;
	for(re int i=1;i<=n;++i)
		for(re int j=1;j<=m;++j)if(a[i][j]){
			if(a[i-1][j])BFS(i-1,j,i,j,0);
			if(a[i][j+1])BFS(i,j+1,i,j,1);
			if(a[i+1][j])BFS(i+1,j,i,j,2);
			if(a[i][j-1])BFS(i,j-1,i,j,3);
		}
	for(re int i=1;i<=q;++i){
		int ex=in,ey=in,sx=in,sy=in,tx=in,ty=in;
		if(sx==tx&&sy==ty){printf("0\n");continue;}
		BFS(ex,ey,sx,sy,-1);
		spfa(sx,sy);
		int ans=INF;
		for(re int j=0;j<4;++j)
			ans=min(ans,dis[get_num(tx,ty)+j]);
		if(ans>=INF) printf("-1\n");
		else printf("%d\n",ans);
	}
	
	return 0;
}

おすすめ

転載: blog.csdn.net/weixin_42557561/article/details/102732616