HDU1181 變形課【DFS+關係閉包+bitset】

變形課

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 38513 Accepted Submission(s): 13646

Problem Description
呃…變形課上Harry碰到了一點小麻煩,因爲他並不像Hermione那樣能夠記住所有的咒語而隨意的將一個棒球變成刺蝟什麼的,但是他發現了變形咒語的一個統一規律:如果咒語是以a開頭b結尾的一個單詞,那麼它的作用就恰好是使A物體變成B物體.
Harry已經將他所會的所有咒語都列成了一個表,他想讓你幫忙計算一下他是否能完成老師的作業,將一個B(ball)變成一個M(Mouse),你知道,如果他自己不能完成的話,他就只好向Hermione請教,並且被迫聽一大堆好好學習的道理.

Input
測試數據有多組。每組有多行,每行一個單詞,僅包括小寫字母,是Harry所會的所有咒語.數字0表示一組輸入結束.

Output
如果Harry可以完成他的作業,就輸出"Yes.",否則就輸出"No."(不要忽略了句號)

Sample Input
so
soon
river
goes
them
got
moon
begin
big
0

Sample Output
Yes.

Hint
Hint
Harry 可以念這個咒語:“big-got-them”.

Source
Gardon-DYGG Contest 1

問題鏈接HDU1181 變形課
問題簡述:(略)
問題分析
    單詞接龍遊戲,看能不能從b接到m。計算算過程中是沒有必要存儲整個單詞,只需要存儲單詞的首尾字符就可以了。可以用DFS來實現,也可以用關係閉包Floyd算法來實現。
    使用關係閉包Floyd算法+位串運算來實現簡單方便快速。
程序說明:DFS處理過程中,使用visit[]數組記憶已經訪問過的單詞。如果找到解則置標誌yesflag爲1,作爲搜索的結束條件。讀入數據時,沒有使用scanf()函數,而是使用getchar()函數。這樣做需要更高的技巧,需要了解更底層的字符流。一次讀入一個字符串的話,需要一個字符數組作爲緩衝存儲,處理時間也會略長。
參考鏈接:(略)
題記:(略)

AC的C++語言程序(關係閉包Floyd算法+位串運算)如下:

/* HDU1181 變形課 */

#include <bits/stdc++.h>

using namespace std;

const int N = 26;
bitset<N> g[N];

inline void reset()
{
    for(int i = 0; i < N; i++) g[i].reset();
}

int main()
{
    string s;

    reset();
    while(cin >> s) {
        if(s == "0") {
            // 位串實現關係閉包計算
            for(int u = 0; u < N; u++)
                for(int v = 0; v < N; v++)
                    if(g[v][u]) g[v] |= g[u];

            cout << (g['b' - 'a']['m' - 'a'] ? "Yes." : "No.") << endl;

            reset();
        } else
            g[s[0] - 'a'][s[s.length() - 1] - 'a'] = 1;
    }

    return 0;
}

AC的C++語言程序(關係閉包Floyd算法)如下:

/* HDU1181 變形課 */

#include <bits/stdc++.h>

using namespace std;

const int N = 26;
int g[N][N];

void floyd()
{
    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++)
            if(g[i][j]) {
                for(int k = 0; k < N; k++)
                    if(g[k][i]) g[k][j] = 1;
            }
}

int main()
{
    string s;

    memset(g, 0, sizeof(g));
    while(cin >> s) {
        if(s == "0") {
            floyd();
            cout << (g['b' - 'a']['m' - 'a'] == 1 ? "Yes." : "No.") << endl;
            memset(g, 0, sizeof(g));
        } else
            g[s[0] - 'a'][s[s.length() - 1] - 'a'] = 1;
    }

    return 0;
}

AC的C++語言程序(DFS)如下:

/* HDU1181 變形課 */  
  
#include <stdio.h>  
#include <memory.h>  
  
#define START 'b'  
#define END 'm'  
  
#define MAXN 1024  
  
char start[MAXN];  
char end[MAXN];  
int visit[MAXN];  
int n;  
int yesflag;  
  
void dfs(char v)  
{  
    int i;  
  
    if(v == END) {  
        yesflag = 1;  
        return;  
    }  
  
    for(i=0; i<n; i++) {  
        if(yesflag)  
            break;  
  
        if(!visit[i] && start[i] == v) {  
            visit[i] = 1;  
            dfs(end[i]);  
            visit[i] = 0;  
        }  
    }  
}  
  
int main(void)  
{  
    char c;  
  
    while((c=getchar()) != EOF) {  
        // 重複讀入n個單詞  
        n = 0;  
        for(;;) {  
            // 首字符  
            start[n] = end[n] = c;  
  
            // 判定字符串結束  
            if(start[n] == '0') {  
                getchar();  // 去除換行符  
                break;  
            }  
  
            // 讀入一行;  
            while((c=getchar()) != '\n')  
                end[n] = c;  
  
            n++;  
  
            c = getchar();  // 下一行的首字符  
        }  
  
        yesflag = 0;  
        memset(visit, 0, sizeof(visit));  
        if(n > 0)  
            dfs(START);  
  
        // 輸出結果  
        if(yesflag)  
            printf("Yes.\n");  
        else  
            printf("No.\n");  
    }  
  
    return 0;  
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章