1. 程式人生 > >UVA1423Guess (dfs,bfs拓撲排序)

UVA1423Guess (dfs,bfs拓撲排序)

題目連結:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36239


題意:給定S( i , j ) , ( i <= j) 的矩陣表示一個數字序列第i個到第j個元素的連續和的符號,‘+’,‘-’,‘0’,求序列的一種可能值。


思路:矩陣中的每個元素都可以看作是序列字首和之差的結果,若設sum(i)為前i個元素的字首和,則S( i, j )表示sum(j)- sum(i)的結果的符號,可以從確定關係的兩個字首和間連一條有向邊,從小的指向大的(反之亦可),然後進行拓撲排序得到sum(i)的一種大小關係。最後對sum(i)依次賦值,即可得到序列。

敲了兩種版本的拓撲排序,dfs 和 bfs兩種版本

程式碼:

dfs版

#include<bits/stdc++.h>
using namespace std;
int G[15][15], vis[15], rec[15][15], ans[15], Ans[15];
int len, n;
void dfs(int u){
    vis[u] = 1;
    for(int i = 0; i <= n; i++){
        if(!vis[i] && G[u][i]) dfs(i);
    }
    ans[len--] = u; //記錄路徑,從後往前記錄
}
int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        len = n;
        memset(G, 0, sizeof(G));
        memset(vis, 0, sizeof(vis));
        memset(rec, 0, sizeof(rec));
        char a;
        getchar();
        for(int i = 1; i <= n; i++){
            for(int j = i; j <= n; j++){
                scanf("%c", &a);
                if(a == '+') G[i-1][j] = 1;
                else if(a == '-') G[j][i-1] = 1;
                else if(a == '0') rec[i-1][j] = rec[j][i-1] = G[i-1][j] = 1;
            }
        }
        for(int i = 0; i <= n; i++)
            if(!vis[i]) dfs(i);
        Ans[ans[0]] = 0;
        for(int i = 1; i <= n; i++){     // 對找到的字首和序列賦值
            if(rec[ans[i]][ans[i-1]]) Ans[ans[i]] = Ans[ans[i-1]];
            else  Ans[ans[i]] = Ans[ans[i-1]] + 1;
        }
        for(int i = 1; i <= n; i++){
            printf("%d%c", Ans[i]-Ans[i-1], i == n?'\n':' ');
        }
    }
    return 0;
}

bfs版

#include<bits/stdc++.h>
using namespace std;
int G[15][15], rec[15], cnt, n, ans[15]; // rec[i]陣列記錄可能比第i個元素小的序列元素的數量
void bfs(){
    queue<int> q;
    while(!q.empty()) q.pop();
    for(int i = 0; i <= n; i++) if(rec[i] == 0) q.push(i);
    while(!q.empty()){
        int sz = q.size();
        for(int i = 0; i < sz; i++){
            int u = q.front(); q.pop();
            ans[u] = cnt;  // 對找到的字首和序列賦值
            for(int v = 0; v <= n; v++){
                if(G[u][v]){
                    rec[v]--;
                    if(rec[v] == 0) q.push(v);
                }
            }
        }
        cnt++;
    }
}
int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        cnt = 0;
        char tmp;
        scanf("%d", &n);
        memset(G, 0, sizeof(G));
        memset(rec, 0, sizeof(rec));
        getchar();
        for(int i = 1; i <= n; i++){
            for(int j = i; j <= n; j++){
                scanf("%c", &tmp);
                if(tmp == '+') G[i-1][j] = 1, rec[j]++;
                else if(tmp == '-') G[j][i-1] = 1, rec[i-1]++;
            }
        }
        bfs();
        for(int i = 1; i <= n; i++){
            printf("%d%c", ans[i]-ans[i-1],  i == n ? '\n' : ' ');
        }
    }
    return 0;
}