A/B/C/D/E五個人互相傳球

A/B/C/D/E五個人互相傳球,由A開始第一次傳球,經5次傳球后傳回到A的手上,其中A與B不會相互傳球,C只會傳給D,E不會傳給C,共有多少種傳法?

思路:
設接球人的序列爲:AXXXXA,其中中間4位是未知的.
根據條件列出不合法的情況,及對應正則:

相鄰兩個相同的(自己不能傳給自己):(.)\1+
A後是B或B後是A的:AB|BA
C後不是D的:C[^D]
E後是C的:EC

拼接起來就是:(.)\1+|AB|BA|C[^D]|EC

先不考慮條件找出所有可能,再把每種可能使用以上規則過濾一遍,得到的就是需求的

實現:

public static void main(String[] args) {
    char[] cs = "ABCDE".toCharArray();
    //不合法字串正則
    Pattern pattern = Pattern.compile("(.)\\1+|AB|BA|C[^D]|EC");
    //由A發球,經過5次傳球又回到A受理,所以中間有4個人接球,求出所有可能
    String[] result = samplingWithReplacement(cs, 4);
    List<String> list = new ArrayList<>();
    for (String s : result) {
        //過濾掉不合法的
        if (!pattern.matcher("A" + s + "A").find()) {
            list.add("A" + s + "A");
        }
    }
    System.out.println(list);
    System.out.println(list.size());
}
/**
 * 使用字符數組中的字符,組成長度爲n的字符串,字符可以重複.
 * 
 * @param chars
 * @param n
 * @return 結果長度爲chars.length^n
 */
public static String[] samplingWithReplacement(char[] chars, int n) {
    String[] preResult;
    if (n < 1)
        throw new IllegalArgumentException("n不能小於1");
    if (n == 1) {
        preResult = new String[] { "" };
    } else {
        preResult = samplingWithReplacement(chars, n - 1);
    }
    String[] result = new String[preResult.length * chars.length];
    int i = 0;
    for (String preString : preResult) {
        for (char c : chars) {
        result[i] = preString + c;
        i++;
        }
    }
    return result;
}

結果:

[ACDADA, ACDAEA, ACDBDA, ACDBEA, ACDCDA, ACDEDA, ADACDA, ADADEA, ADAEDA, ADBCDA, ADBDEA, ADBEDA, ADCDEA, ADEADA, ADEAEA, ADEBDA, ADEBEA, ADEDEA, AEACDA, AEADEA, AEAEDA, AEBCDA, AEBDEA, AEBEDA, AEDADA, AEDAEA, AEDBDA, AEDBEA, AEDCDA, AEDEDA]
30
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章