zoukankan      html  css  js  c++  java
  • uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)

    这题数据大容易TLE

    优化:预处理, 可以先枚举出5^3的状态然后判断合不合法,但是由于题目说了有很多墙壁,实际上没有那么多要转移的状态那么可以把底图抽出来,然后3个ghost在上面跑到时候就不必判断了,减少了两次无用的枚举。

    减少代码的方法:1.结点没有3个时增加冗余点,2.把位置坐标二元组编号成一个数,这点在预处理时可以顺便完成(坐标范围0~15),3.把三个ghost的位置状态压缩成一个数字,方便push,但是注意重时不能直接用Hash掉的值来判断vis,因为Hash以后数字范围很大。

    这题为什么不适合Astar。因为Astar的估计用Manhattan距离需要知道坐标,因此不适合把二元组hash成数字,而且不能用一个数来压缩状态了,因为要加上估价值,代码很长,容易写错。

    学习点:

    1.减少代码量的方法,减少分类,提取不同的问题的相同部分

    2.建图的方法。

    poj不支持#include<bits/stdc++.h>

    //Rey
    #include<bits/stdc++.h>
    using namespace std;
    const int maxw = 16;
    const int maxn = 150;//14*14*3/4+2 149
    
    
    int s[3];
    int t[3];
    int w,h,n;
    char maze[maxw][maxw+1];
    
    
    int deg[maxn],G[maxn][5];
    
    inline bool conflict(int a1,int b1,int a2,int b2){
        return a1 == a2 || (a1 == b2 && a2 == b1);
    }
    int vis1[maxn][maxn][maxn];
    int vis2[maxn][maxn][maxn];
    typedef vector<int> VINT;
    VINT v1;
    VINT v2;
    VINT v3;
    typedef VINT * PV;
    
    inline int Hash(int a,int b,int c) {return a<<16|b<<8|c;}
    int dBfs()
    {
        v1.clear();v2.clear();v3.clear();
        memset(vis1,-1,sizeof(vis1));
        memset(vis2,-1,sizeof(vis2));
        PV q1 = &v1,q2 = &v2,nxt = &v3;
        int (*d1)[maxn][maxn] = vis1, (*d2)[maxn][maxn] = vis2;
        d1[s[0]][s[1]][s[2]] = 0;
        d2[t[0]][t[1]][t[2]] = 0;
        q1->push_back(Hash(s[0],s[1],s[2]));
        q2->push_back(Hash(t[0],t[1],t[2]));
        while(q1->size()&&q2->size()){
            if(q1->size()>q2->size()) swap(q1,q2),swap(d1,d2);
            for(int ii = 0,sz = q1->size(); ii < sz; ii++){
                int u = (*q1)[ii];
                int a = u>>16, b = (u>>8)&0xff, c = u&0xff;
                for(int i = 0; i < deg[a]; i++){
                    int a1 = G[a][i];
                    for(int j = 0; j < deg[b]; j++){
                        int b1 = G[b][j];
                        if(conflict(a1,a,b1,b)) continue;
                        for(int k = 0; k < deg[c]; k++){
                            int c1 = G[c][k];
                            if(conflict(c1,c,a1,a)||conflict(c1,c,b1,b)||~d1[a1][b1][c1]) continue;
                            d1[a1][b1][c1] = d1[a][b][c]+1;
                            if(~d2[a1][b1][c1]) { return d1[a1][b1][c1]+d2[a1][b1][c1]; }
                            nxt->push_back(Hash(a1,b1,c1));
                        }
                    }
                }
            }
            q1->clear();
            swap(nxt,q1);
        }
    
        return -1;
    }
    
    
    void init()
    {
        int cnt = 0;
        int id[maxw][maxw];
        const int dx[] = {-1, 1, 0, 0, 0};
        const int dy[] = { 0, 0,-1, 1, 0};
        int x[maxn];
        int y[maxn];
    
        for(int i = 0; i < h; i++)
        for(int j = 0; j < w; j++) {
            char ch = maze[i][j];
            if(ch != '#'){
                x[cnt] = i; y[cnt] = j;  id[i][j] = cnt;
                if('A'<= ch && ch <= 'C') {t[ch-'A'] = cnt;}
                else if('a' <= ch && ch <= 'c') {s[ch-'a'] = cnt; }
                cnt++;
                }
            }
    
    
        for(int i = 0; i < cnt; i++){
            deg[i] = 0;
             for(int k = 0; k < 5; k++) {
                int nx = x[i]+dx[k], ny = y[i]+dy[k];
                if(maze[nx][ny] != '#')
                    G[i][deg[i]++] = id[nx][ny];
            }
        }
        if(n<=2) {deg[cnt] = 1; G[cnt][0] = cnt; s[2] = t[2] = cnt++; }
        if(n<=1) {deg[cnt] = 1; G[cnt][0] = cnt; s[1] = t[1] = cnt++; }
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&w)&&w) {
            scanf("%d%d
    ",&h,&n);
            for(int i = 0; i < h; i++)
                gets(maze[i]);//G[i-1]
                init();
                int ans = dBfs();
                printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    《Programming WPF》翻译 第8章 1.动画基础
    一些被遗忘的设计模式
    《Programming WPF》翻译 第4章 数据绑定
    《Programming WPF》翻译 第3章 控件
    《Programming WPF》翻译 第5章 样式和控件模板
    《Programming WPF》翻译 第7章 绘图
    《Programming WPF》翻译 第9章 自定义控件
    《Programming WPF》翻译 第7章 绘图 (2)
    《Programming WPF》翻译 第8章 前言
    关于Debug和Release之本质区别
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4625821.html
Copyright © 2011-2022 走看看