poj 3026 bfs+mst(消灭外星人)

题意:给出一个二维字符串,里面有#代表不能走,' '空格代表可以走,然后还有'A'和'S'代表人,问从S到达所有'A'的最小通路,其中S点或者走到一个A点时可以分身。

思路:从其中每个人的位置开始深搜求出到其他点得距离。在这个图上求MST即为所求。

深搜的时候用一维保存位置,4个方向变成了+1,-1,+m,-m。此时需要注意+1和-1是否出现换行的情况。

#include <stdio.h>
#include <string.h>
#define clc(x,t) memset(x,t,sizeof(x));
#define N 105
#define INF 0x3fffffff
int m,n,T;
char s[N][N];
int q[N*N],hash[N*N],id[N*N],ori[4],used[N*N],step[N*N],g[N][N];
void init(){
    clc(step,0);
    clc(used,0);
}
int cd(int i,int j){
    return i*m+j;
}
int test(int x){
    int i = x/m;
    int j = x%m;
    return !used[x] && s[i][j]!='#' && x>=0 && x<m*n;
}
void bfs(int pos){
    int i,rear,front,now,next;
    init();
    rear = front = -1;
    q[++rear] = pos;
    used[pos] = 1;
    while(front < rear){
        now = q[++front];
        for(i = 0;i<4;i++){
            if((i==0 && now%m==m-1) || (i==1 && now%m==0))//图方便用一维来表示位置需要注意这个
                continue;
            next = now+ori[i];
            if(test(next)){
                used[next] = 1;
                q[++rear] = next;
                step[next] = step[now]+1;
                if(hash[next])
                    g[id[pos]][id[next]] = g[id[next]][id[pos]] = step[next];
            }
        }
    }
}
int prim(int n){
    int i,j,mm,pos,res=0;
    memset(used, 0, sizeof(used));
    for(i = 1;i<=n;i++)
        id[i] = INF;
    id[1] = 0;
    for(i = 1;i<=n;i++){
        mm = INF;
        for(j = 1;j<=n;j++)
            if(!used[j] && id[j]<mm){
                pos = j;
                mm = id[j];
            }
        used[pos] = 1;
        res+=mm;
        for(j = 1;j<=n;j++)
            if(!used[j] && id[j]>g[pos][j])
                id[j] = g[pos][j];
    }
    return res;
}
int main(){
    scanf("%d",&T);
    ori[0] = 1,ori[1] = -1;
    while(T--){
        int i,j,k;
        char ch;
        clc(hash,0);
        clc(id,0);
        scanf("%d %d",&m,&n);
        while((ch=getchar())!='\n');
        ori[2] = m,ori[3] = -m;
        for(i = 0;i<n;i++)
            gets(s[i]);
        for(i = k = 0;i<n;i++)
            for(j = 0;j<m;j++)
                if(s[i][j]=='A' || s[i][j]=='S'){
                    hash[cd(i,j)] = 1;
                    id[cd(i,j)] = ++k;
                }
        for(i = 0;i<n*m;i++)
            if(hash[i])
                bfs(i);
        printf("%d\n",prim(k));
    }
    return 0;
}


你可能感兴趣的:(poj 3026 bfs+mst(消灭外星人))