zoukankan      html  css  js  c++  java
  • 3537. 【NOIP2013提高组day2】华容道(搜索 + 剪枝)

    Problem

    给出一个类似华容道的图。(q)次询问,每次给你起始点,终止点,空格位置,让你求最少步数

    (n,mle 30, qle 500).

    Soultion

    一道智障搜索题。

    弱智想法最多80分。不用想了。我已经试过所有非O2的常数优化,还是有1.05秒。

    考虑一下预处理。

    事实上,我们发现只有当空格位置在初始点旁边时才会影响初始点(废话),所以我们可以先预处理在某一个点((x,y))的四周,不经过这个点(x,y),到达这个点四周的最少步数。BFS解决。

    然后每次询问时,就先把空格位置跑到初始点的四周,然后每次用预处理的去更新。

    Code
    #include <bits/stdc++.h>
    
    #define I register int
    #define F(i, a, b) for (I i = a; i <= b; i ++)
    #define mem(a, b) memset(a, b, sizeof a)
    
    const int N = 31;
    
    const int dx[4] = { 1, 0 , 0, - 1};
    const int dy[4] = { 0, - 1 , 1, 0};
    
    using namespace std;
    
    int h, t, Ans, ex, ey, sx, sy, tx, ty;
    int n, m, q, a[N + 1][N + 1];
    int f[N][N][4], bz[N][N][N][N], vis[N][N];
    struct node {
    	int x, y, k;
    } d[N * N * N];
    struct Node {
    	int x, y;
    } D[N * N];
    
    void Doit() {
    	int st = 0, en = 0;
    
    	mem(f, 7), h = 0, D[t = 1] = {ex, ey}, mem(vis, 0), vis[ex][ey] = 1;
    	F(p, 0, 3) {
    		I xxx = ex + dx[p], yyy = ey + dy[p];
    		if (a[xxx][yyy] && xxx == sx && yyy == sy)
    			d[++ en] = {ex, ey, 3 - p}, f[ex][ey][3 - p] = 1;
    	}
    	while (h ++ < t) {
    		I x = D[h].x, y = D[h].y;
    		F(k, 0, 3) {
    			I xx = x + dx[k], yy = y + dy[k];
    			if (a[xx][yy] && !vis[xx][yy] && !(xx == sx && yy == sy)) {
    				vis[xx][yy] = vis[x][y] + 1, D[++ t] = {xx, yy};
    				F(p, 0, 3) {
    					I xxx = xx + dx[p], yyy = yy + dy[p];
    					if (a[xxx][yyy] && xxx == sx && yyy == sy)
    						d[++ en] = {xx, yy, 3 - p}, f[xx][yy][3 - p] = vis[xx][yy];
    				}
    			}
    		}
    	}
    
    	while (st ++ < en) {
    		I x = d[st].x, y = d[st].y, k = d[st].k;
    		F(p, 0, 3) {
    			I xx = x + dx[p], yy = y + dy[p];
    			if (a[xx][yy] && f[xx][yy][p] > f[x][y][k] + bz[x][y][k][3 - p]) {
    				f[xx][yy][p] = f[x][y][k] + bz[x][y][k][3 - p];
    				d[++ en] = {xx, yy, p};
    			}
    		}
    	}
    
    	int Ans = 1e8;
    	F(k, 0, 3)
    		Ans = min(Ans, f[tx][ty][k]);
    	printf("%d
    ", Ans == 1e8 ? - 1 : Ans);
    }
    
    int main() {	
    	scanf("%d%d%d", &n, &m, &q);
    	F(i, 1, n)
    		F(j, 1, m)
    			scanf("%d", &a[i][j]);
    
    	mem(bz, 7);
    	F(i, 1, n)
    		F(j, 1, m) {
    			if (!a[i][j]) continue;
    			F(k, 0, 3) {
    				int x = i + dx[k], y = j + dy[k], w = k;
    				if (!a[x][y]) continue;
    				h = 0, D[t = 1] = {x, y}, mem(vis, 0), bz[i][j][w][w] = 1, vis[x][y] = 1;
    				while (h ++ < t) {
    					x = D[h].x, y = D[h].y;
    					F(k, 0, 3) {
    						int xx = x + dx[k], yy = y + dy[k];
    						if (a[xx][yy] && !(xx == i && yy == j) && !vis[xx][yy]) {
    							vis[xx][yy] = vis[x][y] + 1, D[++ t] = {xx, yy};
    							F(k, 0, 3) {
    								int xxx = xx + dx[k], yyy = yy + dy[k];
    								if (a[xxx][yyy] && xxx == i && yyy == j)
    									bz[i][j][3 - w][k] = vis[xx][yy];
    							}
    						}
    					}
    				}
    			}
    		}
    
    	F(i, 1, q) {
    		scanf("%d%d%d%d%d%d", &ex, &ey, &sx, &sy, &tx, &ty);
    		if (sx == tx && sy == ty) {
    			puts("0");
    			continue;
    		}
    		Doit();
    	}
    }
    
  • 相关阅读:
    字符编码
    模和同余定理
    数的编码
    Win32 Error Code COM Error Code NTSTATUS的区别、转换
    Error Codes Messages查找工具介绍
    NTSTATUS
    COM Error Code(HRESULT)部分摘录
    COM Error---HRESULT
    Win32 Error
    windows错误代码摘录
  • 原文地址:https://www.cnblogs.com/Pro-king/p/10686303.html
Copyright © 2011-2022 走看看