zoukankan      html  css  js  c++  java
  • noip2013day2T3华容道

    这道题,写的很醉啊。。。。

    这种搜索的题,还带一点DP,各种bug调了好久,

    思路:

    60分做法就直接bfs乱搞,60分到手;

    ac套路:

    首先预处理出f[i][j][k]状态,对于点ij,空格在k方向就是开个【30】【30】【4】的数组,再用邻接表存下来,spfa跑一边最短路就好了,注意终点和起点是可能重合的;

    code:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    const int N=35;
    const int M=400010;
    const int inf=1000000000;
    using namespace std;
    bool vis[N][N];
    const int d[4][2]={{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    struct point{
    	int x, y, d;
    };
    int n,m,q,map[N][N];
    int bfs(int x1, int y1, int x2, int y2){
    	for(int i=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j)vis[i][j]=false;
    	vis[x1][y1]=true;
    	queue<point>q;
    	q.push((point){x1, y1, 0});
    	while(!q.empty()){
    		int x=q.front().x,y=q.front().y,dd=q.front().d;
    		if(x==x2 && y==y2)return dd;
    		q.pop();
    		for(int i=0;i<=3;++i){
    			int u=x+d[i][0];
    			int v=y+d[i][1];
    			if(map[u][v] && !vis[u][v]){
    				vis[u][v]=1;
    				q.push((point){u,v,dd+1});
    			}
    		}
    	}
    	return inf;
    }
    int start[M],nxt[M],to[M],w[M],e;  
    void add(int x, int y, int z){
    	to[++e]=y;
    	nxt[e]=start[x];
    	start[x]=e;
    	w[e]=z;
    }
    int f[N][N][4],cnt;
    void pre(){
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			for(int k=0;k<=3;++k)
    				f[i][j][k]=++cnt;
    	int t;
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j){
    			if(map[i][j])map[i][j]=0;else continue;
    			for(int k=0;k<=3;++k)
    				for(int l=0;l<=3;++l){
    					int x1=i+d[k][0],y1=j+d[k][1],x2=i+d[l][0],y2=j+d[l][1];
    					if(map[x1][y1] && map[x2][y2]){
    						t=bfs(x1,y1,x2,y2);
    						if(t<inf)add(f[i][j][k],f[x2][y2][l^1],t+1);
    					}
    				}
    			map[i][j]=1;
    		}
    }
    int p[M],dis[M];
    int spfa(int s,int t){
    	queue<int>q;
    	for(int i=1;i<=cnt;++i)dis[i]=inf,p[i]=0;
    	p[s]=1;
    	q.push(s);
    	dis[s]=0;
    	while(!q.empty()){
    		int u=q.front();
    		p[u]=0;
    		q.pop();
    		for(int i=start[u];i;i=nxt[i]){
    			int v=to[i];
    			if(dis[v]>dis[u]+w[i]){
    				dis[v]=dis[u]+w[i];
    				if(!p[v])q.push(v);
    				p[v]=1;
    			}
    		}
    	}
    	return dis[t]<inf?dis[t]:-1;
    }
    int main(){
    	int x,y,x1,y1,x2,y2,t;
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			scanf("%d",&map[i][j]);
    	pre();
    	for(int i=1;i<=q;++i){
    		int S=++cnt,T=++cnt;
    		scanf("%d%d%d%d%d%d",&x,&y,&x1,&y1,&x2,&y2);
    		if(x1==x2 && y1==y2){
    			puts("0");continue;
    		}
    		if(!map[x1][y1] || !map[x2][y2]){
                puts("-1");
                continue;
            }
            map[x1][y1]=0;
    //搜索出空格的移动状态
           for(int j=0;j<=3;++j){
                int u=x1+d[j][0],v=y1+d[j][1];
                if(map[u][v]){
                    int t=bfs(x, y, u, v);
                    if(t < inf)add(S, f[x1][y1][j], t);
                }
            }
    		map[x1][y1]=1;
            for(int j=0;j<=3;++j){
                int u=x2+d[j][0],v=y2+d[j][1];
                if(map[u][v])add(f[x2][y2][j], T, 0);
            }
    		printf("%d
    ",spfa(S,T));
    	}
    }


  • 相关阅读:
    教你Python3实现12306火车票自动抢票,小白必学
    Spring Security 中如何快速查看登录 IP地址等信息?一招搞定
    方程组及其解的判定
    向量空间
    极大无关组和向量组等价
    向量组的线性相关与线性无关
    向量间的线性关系
    向量的概念和运算
    矩阵的秩和秩的性质
    利用初等变换求逆矩阵和解矩阵方程
  • 原文地址:https://www.cnblogs.com/pbvrvnq/p/8530173.html
Copyright © 2011-2022 走看看