10776 Determine The combination

題目:http://luckycat.kshs.kh.edu.tw/homework/q10776.htm 觀念:DFS 難度:luckycat ★★---

在 排列組合的課程中老師給了一個作業,要從字串 s 中產生所有的長度為 r 的組合。所謂長度為 r 的組合指的是從字串 s 中挑選 r 個字元。對於相同的組合,但是排列不同的,只考慮 r 個字元為 「非遞減(non-decreasing)」順序的那個。例如:ab 與 ba 為相同的組合,我們只要產生 ab 就好。

所給的字串中只會有小寫的字元,但是相同的字元可能會出現超過一次。請參考Sample Inout, Sample Output。

輸入

輸 入含有多筆測資。每筆測資一列,含有一個字串 s(長度介於 1 到 30 之間)和一個整數 r(0 < r <= s的長度)。

輸出

請 每筆測資輸出所有從 s 中產生長度為 r 的不同的組合。每個組合一列,按字典數序輸出。你可以確定最多只會有1000個不同的組合。

Sample Input

abcde 2
abcd 3
aba 2

Sample Output

ab
ac
ad
ae
bc
bd
be
cd
ce
de

abc
abd
acd
bcd

aa
ab

解題想法

  • 字母輸入的順序可以隨意,所以我們要將收到的按照順序分類並且記錄每種字母的個數
  • 所以babcaa會被轉成 a = 3, b = 2, c = 1 的形式記錄下來
  • 因為ab跟ba是重複的,會取用ab,所以我們在求答案時都會先用a再來是b,c,d,e......
  • 放完a後下一個也接著放a,變成aa,如果沒有a可以放才接著放b或c之類的字母
  • 當a還有剩,但是字串的長度已經到我們輸入的n時,假如說n=2,那麼aa就是其中一個答案,把它cout出來

解答

#include <bits/stdc++.h>
#include <algorithm>
#include <string.h>
using namespace std;

//ch紀錄字母,ch_num紀錄字母出現的次數
char ch[50];
int ch_num[50];
char ans[50];
int charTypeCount;

void dfs(int, int, int);

int main() {

    // 輸入 abdbcaa 4
    // sort 後 abdbcaa 會變成 aaabbcd
    // ch     => {'a','b','c','d'}
    // ch_num => { 3 , 2 , 1 , 1 }

    char str[30]; //要輸入的字串,如:abcde
    int n, len, i, j;

    while(cin>>str>>n) { //舉例:abcde 2

        len = strlen(str); //sizeof(str)也可以

        sort(str, str+len); // abdbcaa會變成aaabbcd

        //將重複的字母計數處理
        ch[0] = str[0], ch_num[0] = 1;
        for(i = 1, j = 0; i < len; i++) {
            if(str[i] != str[i-1]) {
                j++;
                ch[j] = str[i];
                ch_num[j] = 1;
            } else {
                ch_num[j]++;
            }
        }

        charTypeCount = j+1; //charTypeCount為字母種類數量,範例為4

        dfs(n, 0, 0);
    }
    return 0;
}

void dfs(int n, int i, int lastIndex) {
    if(n == 0) {
        //找出其中一個解答,則輸出該解答
        puts(ans);//輸出char陣列,也可用for迴圈輸出
        return;
    }

    for(; i < charTypeCount; i++) {
        if(ch_num[i]) {
            ch_num[i]--; //假如說a有3個,因為其中一個a被放進答案裡面,所以a變2個
            ans[lastIndex] = ch[i]; //答案的最後一格放入目前的字母
            dfs(n-1, i, lastIndex+1);
            ch_num[i]++; //因為dfs在往回走,a這字母又從答案中被退出來,所以從2個變回3個,
        }
    }
}

results matching ""

    No results matching ""