#11959: 迭代演算法


a22124186 (PROC ARC)

學校 : 臺北市立成功高級中學
編號 : 60110
來源 : [124.155.183.186]
最後登入時間 :
2017-04-30 13:48:32
a229. 括號匹配問題 -- 名題精選百則 | From: [140.113.65.108] | 發表日期 : 2017-04-28 14:06

基於迭代比遞迴來得快,我實作了一個迭代的版本,不過時間好像都卡在輸出部分因此沒有什麼幫助,為了解決輸出問題,我將所有要印的字串全都先放在string裡,最後再一次輸出,這樣能減少 system call 的次數而讓程式更快這在遞迴方法裡很

難辦到,而在我電腦上執行的時間也有相當的改進,只是放到server端執行時仍然是TLE,不明所以...    不過我還是想分享一下:)

(題外話: 在我的電腦上當輸入到 10 時,因為作業系統沒辦法在一個時間片段裡印完所有資料,所以輸出會被中斷,這會使得輸出是一塊一塊地被印出來)

我的方法是這樣的:

    以 0 代表左括號、以 1 代表右括號

    限制: 不管在任何位置,左邊 0 的總數都必須大於等於 1 的總數,也可以說成,不管在任何位置,右邊 1 的總數都必須大於等於 0 的總數

    接著假設我們要印 N 組括號,並設一個數字 d 為 dN-1 ~ d0 (ex: N = 3, d = d2d1d0), d0 代表從右邊算起第1個右括號的右邊共有幾個左括號,同理類推

    推論: 因第 n+1 個右括號的右邊有 n 個右括號,由限制可推得 dn (第 n+1 個右括號) 右邊至多只能有 n 個左括號,所以 dn <= n        --- 1

            接著因累加的關係前面的左括號總和不可能大於後面的左括號總和,所以 dN-1 >= dN-2 >= ... >= d2 >= d1 >= d0        --- 2

    演算法: (以 N = 3 為例)

        第一步: 用規則一和二生成所有可能數字

        結果:  000

                 100

                 110

                 200

                 210

       第二步: 根據定義印出括號

                  ex: 210 代表第 1 個右括號右邊有 0 個左括號, 第 2 個到第 1 個右括號之間有 1-0=1 個左括號, 第 3 個到第 2 個右括號之間有 2-1=1 個左括號, 最後補上 3-2=1 個尚未被印出的左括號,得到 ()()()

       結果:  000 ---> 000 ---> ((()))

                100 ---> 100 ---> (()())

                110 ---> 010 ---> (())()

                200 ---> 200 ---> ()(())

                210 ---> 110 ---> ()()()

 

最後反正程式碼是TLE,附上應該沒關係吧lol

#include <iostream>

#include <string>

//#include <time.h>

using namespace std;

void brackets_generator(int);bool compute_next_number(int, int *, int &);

bool compute_next_number(int, int *, int &);

void show(int, const int *, string &s);

int main()
{

    //time_t t1, t2;

    int N;

    while(cin >> N){

        //t1 = clock();

        brackets_generator(N);

        //t2 = clock();

        //cout << "time cost: " << t2-t1 << "\n";

        cout << "\n";

    }

    return 0;

}

bool compute_next_number(int N, int *number, int &index)
{

    if (index == N)

        return false;

    // find next number

    int check = number[index];

    int pos;

    for(pos=index; pos<N-1; ++pos){

       if(number[pos+1] != check)

           break;

    }

    ++number[pos];

    for(int i=1; i<pos; ++i)

        number[i] = 0;

    // update index

    for(index=1; index<N; ++index)

        if(number[index] != index)

            break;

    return true;
}

void show(int N, const int *number, string &s)
{

    for(int i=0; i<N-number[N-1]; ++i)

        s = s + "(";

    for(int i=N-1; i>0; --i){

        s = s + ")";

        for(int j=0; j<number[i]-number[i-1]; ++j)

            s = s + "(";

    }

    s = s + ")" + "\n";
}

void brackets_generator(int N)
{

    string s;

    int *number = new int[N];

    int index = 1;

    for(int i=0; i<N; ++i)

        number[i] = 0;

    show(N, number, s);

    while(compute_next_number(N, number, index))

        show(N, number, s);

    cout << s;

    delete number;
}

 
#11964: Re:迭代演算法


a22124186 (PROC ARC)

學校 : 臺北市立成功高級中學
編號 : 60110
來源 : [124.155.183.186]
最後登入時間 :
2017-04-30 13:48:32
a229. 括號匹配問題 -- 名題精選百則 | From: [124.155.183.186] | 發表日期 : 2017-04-30 13:58

後來我拿去在 linux 上跑,速度顯然慢了很多,這個作法看看就好XD

((看來原本我使用的 codeblocks 有點問題...  一塊一塊印出也可能是它的問題...

 
ZeroJudge Forum