码迷,mamicode.com
首页 > 其他好文 > 详细

1601 - The Morning after Halloween(BFS)

时间:2015-08-11 10:12:57      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:acm   uva   bfs   搜索   

该题时限还是比较宽的,但是如果纯BFS还是会超时,所以要注意题目中的暗示 :任何一个2*2子网格中至少有一个障碍格 。  这表明障碍格有很多,那么重复搜索这些障碍格将会造成极大的浪费(因为我们开了三维数组记录三个鬼的状态,格子越多,状态也会以三次方的速度增加)。  所以我们可以将不是障碍的格子提出来再建一张图,用邻接表的方式。

那么怎么来建图呢? 受坐标离散化的启发,我们可以将每一个有用的格子映射成一个数字 ,作为它的标号 ,然后就可以方便的处理了 。

细节见代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 260;
int w,h,n,d[maxn][maxn][maxn],s[5],t[5],deg[maxn],g[maxn][maxn];
char a[20][20];
int dx[] = { 0,1,0,-1,0 };
int dy[] = { 1,0,-1,0,0 };
struct node{
    int a,b,c;
    node(int a=0,int b=0,int c=0) : a(a),b(b),c(c) {}
};
bool conflict(int a,int b,int a2,int b2) {
    return a2 == b2 || (a2 == b && a == b2); //两个鬼移动到同一个地方,或者移动到对方的地方
}
int bfs() {
    queue<node> q;
    memset(d,-1,sizeof(d));
    q.push(node(s[0],s[1],s[2]));
    d[s[0]][s[1]][s[2]] = 0;
    while(!q.empty()) {
        node u = q.front(); q.pop();
        if(u.a == t[0] && u.b == t[1] && u.c == t[2]) return d[u.a][u.b][u.c];
        for(int i=0;i<deg[u.a];i++) {
            int a2 = g[u.a][i];
            for(int j=0;j<deg[u.b];j++) {
                int b2 = g[u.b][j];
                if(conflict(u.a,u.b,a2,b2)) continue;
                for(int k=0;k<deg[u.c];k++) {
                    int c2 = g[u.c][k];
                    if(conflict(u.a,u.c,a2,c2)) continue;
                    if(conflict(u.b,u.c,b2,c2)) continue;
                    if(d[a2][b2][c2] != -1) continue;
                    d[a2][b2][c2] = d[u.a][u.b][u.c] + 1;
                    q.push(node(a2,b2,c2));
                }
            }
        }
    }
    return -1;
}
int main() {
    while(~scanf("%d%d%d",&w,&h,&n)) {
        if(!w && !h && !n) return 0;
        char c = getchar(); c = getchar();
        for(int i=0;i<h;i++) gets(a[i]);
        int cnt = 0,x[maxn],y[maxn],id[20][20];
        for(int i=0;i<h;i++)
            for(int j=0;j<w;j++) {
                if(a[i][j] != '#') {
                    x[cnt] = i; y[cnt] = j; id[i][j] = cnt;
                    if(islower(a[i][j])) s[a[i][j]-'a'] = cnt;//鬼的初始位置
                    else if(isupper(a[i][j])) t[a[i][j]-'A'] = cnt;//鬼的终止位置
                    ++cnt;
                }
            }
        for(int i=0;i<cnt;i++) {
            deg[i] = 0;
            for(int dir = 0; dir < 5; dir++) {
                int nx = dx[dir]+x[i] , ny = dy[dir]+y[i];
                if(a[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++; }
        printf("%d\n",bfs());
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

1601 - The Morning after Halloween(BFS)

标签:acm   uva   bfs   搜索   

原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/47414425

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!