準備機試Day1-01 bfs+最小生成樹 poj3026

題意:在一個y行,x列的迷宮中,有可行走的通路空格‘ ‘,不可行走的牆’#’,還有兩種英文字母A和S,現在從S出發,要求用最短的路徑L連接所有字母,輸出這條路徑L的總長度。

先bfs求兩兩字母間最短路,作爲圖的邊

然後用prim算法求圖的最小生成樹
prim算法(摘自百度百科):

算法描述

編輯
1).輸入:一個加權連通圖,其中頂點集合爲V,邊集合爲E;
2).初始化:Vnew = {x},其中x爲集合V中的任一節點(起始點),Enew = {},爲空;
3).重複下列操作,直到Vnew = V:
a.在集合E中選取權值最小的邊<u, v>,其中u爲集合Vnew中的元素,而v不在Vnew集合當中,並且v∈V(如果存在有多條滿足前述條件即具有相同權值的邊,則可任意選取其中之一);
b.將v加入集合Vnew中,將<u, v>邊加入集合Enew中;
4).輸出:使用集合Vnew和Enew來描述所得到的最小生成樹
代碼:
#include<iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int R,C;
char grid[1000][1000];
int tag[1000][1000];
bool vis[1000][1000];
int len[1000][1000];
int mov[4][2] = {{1,0},{0,-1},{-1,0},{0,1}};
bool is_in[5000];
char temp[510];

struct node{
    int r,c;
    int step;
}s[5000];

void bfs(int u){
    node t1,t2;
    queue<node> q;
    t1.r = s[u].r;
    t1.c = s[u].c;
    t1.step = 0;
    vis[t1.r][t1.c] = true;
    q.push(t1);
    while(!q.empty()){
        t1 = q.front();
        q.pop();
        int v = tag[t1.r][t1.c];
        if(v!=-1){
            len[u][v] = len[v][u] = t1.step;
        }
        for(int i=0;i<4;i++){
            t2.r = t1.r + mov[i][0];
            t2.c = t1.c + mov[i][1];
            if(t2.r<R && t2.r>=0 && t2.c<C && t2.c>=0){
                if(vis[t2.r][t2.c]==false && grid[t2.r][t2.c]!='#'){
                    vis[t2.r][t2.c] = true;
                    t2.step = t1.step + 1;
                    q.push(t2);
                }
            }
        }
    }

}

int main(){
    int T,i,j,k;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&C,&R);
        memset(tag,-1,sizeof(tag));
        memset(len,-1,sizeof(len));
        gets(temp);
        for(i=0;i<R;i++){

            gets(grid[i]);
        }
        k=1;
        for(i=0;i<R;i++){
            for(j=0;j<C;j++){
                if(grid[i][j]=='S' || grid[i][j]=='A'){
                    s[k].r = i;
                    s[k].c = j;
                    tag[i][j]=k++;
                }
            }
        }

        for(i=1;i<k;i++){
            memset(vis,false,sizeof(vis));
            bfs(i);
        }

        memset(is_in,false,sizeof(is_in));
        is_in[1] = true;


        int ans = 0;
        //求最小生成樹
        while(true){

            int t = 1000000000;
            int pos = -1;

            for(i=1;i<k;i++){
                if(is_in[i]){

                    for(j=1;j<k;j++){
                        //if(j == i) continue;
                        if(!is_in[j]){
                            if(t>len[i][j]){
                                t = len[i][j];
                                pos = j;
                            }
                        }
                    }

                }
            }

            if(pos == -1) break;
            is_in[pos] = true;
            ans += t;

        }
        printf("%d\n",ans);


    }
    return 0;

}
wa了兩次..之前用getchar()喫掉輸入整數後面的換行不知道爲啥wa..看disscus改成gets一個字符串就過了,是測試數據裏有空格..然後數組改大就能過。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章