The Morning after Halloween(待优化)

网址如下:

The Morning after Halloween - UVA 1601 - Virtual Judge (vjudge.net)

感觉自己和废物一样,除了用bfs啥都不会,顶多改改其中的细节

代码如下:

#include<cstdio>
#include<vector>
#include<cstring>
#include<cctype>
#include<queue>
using namespace std;

const int maxwh = 16;
const int maxn = 3;
const int x[5]{-1, 1, 0, 0, 0};//上下左右停
const int y[5]{0, 0, -1, 1, 0};

struct Node{
    int g_x[maxn], g_y[maxn], dist;
    Node():dist(0){memset(g_x, 0, sizeof(g_x)); memset(g_y, 0, sizeof(g_y));}
};

vector<int> G[maxwh][maxwh];
char map[maxwh][maxwh];
int w, h, n, ans;
int vis[maxwh][maxwh][maxwh][maxwh][maxwh][maxwh];
int t_x[maxn], t_y[maxn];
queue<Node> q;
Node v;

void init(void){
    memset(vis, 0, sizeof(vis));
    memset(t_x, 0, sizeof(t_x));
    memset(t_y, 0, sizeof(t_y));
}
void update_G(void){
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            G[i][j].clear();
            if(map[i][j] != '#'){
                G[i][j].push_back(4);
                for(int m = 0; m < 4; m++){
                    int _x = i + x[m], _y = j + y[m];
                    if(_x >= 0 && _y >= 0 && _x < h && _y < w && map[_x][_y] != '#') G[i][j].push_back(m);
                }
            }
        }
    }
}
bool is_arrived(Node &u){
    for(int i = 0; i < n; i++)
        if(u.g_x[i] != t_x[i] || u.g_y[i] != t_y[i]) return false;
    return true;
}
void move(Node &u, int i){
    if(i == maxn){
        v.dist = u.dist + 1;
        bool is = true;
        //判断是否占用同一位置
        for(int i = 0; i < n; i++)
            for(int j = i + 1; j < n; j++)
                if(is && v.g_x[i] == v.g_x[j] && v.g_y[i] == v.g_y[j]) is = false;
        //判断是否交换位置
        for(int i = 0; i < n; i++)
            for(int j = i + 1; j < n; j++)
                if(is && v.g_x[i] == u.g_x[j] && v.g_y[i] == u.g_y[j] && v.g_x[j] == u.g_x[i] && v.g_y[j] == u.g_y[i]) is = false;
        if(is) q.push(v);
        return;
    }
    if(i >= n){v.g_x[i] = v.g_y[i] = 0; move(u, i + 1);}
    else{
        vector<int> &tmp = G[u.g_x[i]][u.g_y[i]];
        for(auto it = tmp.begin(); it != tmp.end(); it++){
            v.g_x[i] = u.g_x[i] + x[*it];
            v.g_y[i] = u.g_y[i] + y[*it];
            move(u, i + 1);
        }
    }
}
void bfs(void){
    while(!q.empty()){
        Node u = q.front(); q.pop();
        if(vis[u.g_x[0]][u.g_y[0]][u.g_x[1]][u.g_y[1]][u.g_x[2]][u.g_y[2]] && u.dist > vis[u.g_x[0]][u.g_y[0]][u.g_x[1]][u.g_y[1]][u.g_x[2]][u.g_y[2]]) continue;
        vis[u.g_x[0]][u.g_y[0]][u.g_x[1]][u.g_y[1]][u.g_x[2]][u.g_y[2]] = u.dist;
        if(is_arrived(u)){ans = u.dist; break;}
        //移动
        move(u, 0);
    }
    while(!q.empty()) q.pop();
}

int main(void)
{
    while(scanf("%d%d%d", &w, &h, &n) == 3 && w){
        getchar(); init();
        //输入地图
        Node tmp;
        for(int i = 0; i < h; i++){
            for(int j = 0; j < w; j++){
                char c = getchar(); map[i][j] = c;
                if(isupper(c)){t_x[c - 'A'] = i; t_y[c - 'A'] = j;}
                else if(islower(c)){tmp.g_x[c - 'a'] = i; tmp.g_y[c - 'a'] = j;}
            }
            getchar();
        }
        update_G();//更新空格图
        q.push(tmp);
        bfs();
        printf("%d\n",ans);
    }

    return 0;
}

这题比较炸裂的一点在于,移动的点可以高达3个,一次可以延申出来的状态有5*5*5 = 125个

纵使题目表明有很多障碍,可以延申出来的状态也是很多

同时,我已经根据给出的地图重新建立了一个图(就是那个G数组)来记录该点合法的移动方向,但是最后还是超时了

但是状态的记录倒是没多大问题,因为地图很小,纵使使用占用内存最大的哈希表也不会让内存爆炸

说是可以换一个算法,比如双向广度优先搜索,但是我感觉这玩意对效率的提升并没有什么帮助(话虽如此,我也还没有尝试)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值