演算法和資料結構面試題(15)-8張撲克的遊戲__JAVA

來源:互聯網
上載者:User
題目


有4 張紅色的牌和4 張藍色的牌,主持人先拿任意兩張,再分別在A、B、C 三人額頭上貼任意兩張牌,A、B、C 三人都可以看見其餘兩人額頭上的牌,看完後讓他們猜自己額頭上是什麼顏色的牌,A 說不知道,B 說不知道,C 說不知道,然後A 說知道了。請教如何推理,A 是怎麼知道的。如果用程式,又怎麼實現呢。

解題思路


首先組合的情形是3×3×3 = 27


public void group() {        String[] arg = { "藍-藍", "紅-紅", "紅-藍" };        int size = arg.length;        int index = 0;        for (int i = 0; i < size; i++) {            String A = arg[i];            for (int j = 0; j < size; j++) {                String B = arg[j];                for (int k = 0; k < size; k++) {                    String C = arg[k];                    index++;                    String group = String.format("%s-%s-%s", A, B, C);                    String groupStr = String.format("%s %s %s", A, B, C);                    System.out.print(index + ": ");                    System.out.println(groupStr);                }            }        }    }

1: 藍-藍 藍-藍 藍-藍2: 藍-藍 藍-藍 紅-紅3: 藍-藍 藍-藍 紅-藍4: 藍-藍 紅-紅 藍-藍5: 藍-藍 紅-紅 紅-紅6: 藍-藍 紅-紅 紅-藍7: 藍-藍 紅-藍 藍-藍8: 藍-藍 紅-藍 紅-紅9: 藍-藍 紅-藍 紅-藍10: 紅-紅 藍-藍 藍-藍11: 紅-紅 藍-藍 紅-紅12: 紅-紅 藍-藍 紅-藍13: 紅-紅 紅-紅 藍-藍14: 紅-紅 紅-紅 紅-紅15: 紅-紅 紅-紅 紅-藍16: 紅-紅 紅-藍 藍-藍17: 紅-紅 紅-藍 紅-紅18: 紅-紅 紅-藍 紅-藍19: 紅-藍 藍-藍 藍-藍20: 紅-藍 藍-藍 紅-紅21: 紅-藍 藍-藍 紅-藍22: 紅-藍 紅-紅 藍-藍23: 紅-藍 紅-紅 紅-紅24: 紅-藍 紅-紅 紅-藍25: 紅-藍 紅-藍 藍-藍26: 紅-藍 紅-藍 紅-紅27: 紅-藍 紅-藍 紅-藍

然後再通過一些條件過濾掉上面組合中一些選項


條件1.組合中的紅的數量或者藍的數量不能超過4


public void group() {String[] arg = { "藍-藍", "紅-紅", "紅-藍" };int size = arg.length;int index = 0;for (int i = 0; i < size; i++) {String A = arg[i];for (int j = 0; j < size; j++) {String B = arg[j];for (int k = 0; k < size; k++) {String C = arg[k];index++;String group = String.format("%s-%s-%s", A, B, C);String groupStr = String.format("%s %s %s", A, B, C);if (getStrCount(group)) {System.out.print(index + ": ");System.out.println(groupStr);}}}}}public boolean getStrCount(String str) {String[] args = str.split("-");int blueCount = 0;int redCount = 0;for (int i = 0; i < args.length; i++) {if (args[i].equals("藍")) {blueCount++;} else if (args[i].equals("紅")) {redCount++;}}if (blueCount > 4 || redCount > 4) {return false;}return true;}


過濾掉上面編號為1,3,7,14,15,17,19,23八種情況。還剩19種。


2: 藍-藍 藍-藍 紅-紅4: 藍-藍 紅-紅 藍-藍5: 藍-藍 紅-紅 紅-紅6: 藍-藍 紅-紅 紅-藍8: 藍-藍 紅-藍 紅-紅9: 藍-藍 紅-藍 紅-藍10: 紅-紅 藍-藍 藍-藍11: 紅-紅 藍-藍 紅-紅12: 紅-紅 藍-藍 紅-藍13: 紅-紅 紅-紅 藍-藍16: 紅-紅 紅-藍 藍-藍18: 紅-紅 紅-藍 紅-藍20: 紅-藍 藍-藍 紅-紅21: 紅-藍 藍-藍 紅-藍22: 紅-藍 紅-紅 藍-藍24: 紅-藍 紅-紅 紅-藍25: 紅-藍 紅-藍 藍-藍26: 紅-藍 紅-藍 紅-紅27: 紅-藍 紅-藍 紅-藍

條件2.A不知道,B不知道,C不知道。說明三個人當中不能每個人手裡的兩張牌都是一樣的顏色。


反證法:如果出現三個人當中每個人手裡的牌都是顏色一樣的。那麼第一次的時候,3個人當中一眼就直接能猜出來了。


public void group() {String[] arg = { "藍-藍", "紅-紅", "紅-藍" };int size = arg.length;int index = 0;for (int i = 0; i < size; i++) {String A = arg[i];for (int j = 0; j < size; j++) {String B = arg[j];for (int k = 0; k < size; k++) {String C = arg[k];index++;String groupStr = String.format("%s %s %s", A, B, C);// 條件1String group = String.format("%s-%s-%s", A, B, C);if (!getStrCount(group))continue;// 條件2if (!isEveryOneSame(A) && !isEveryOneSame(B)&& !isEveryOneSame(C))continue;System.out.print(index + ": ");System.out.println(groupStr);}}}}// 條件2    private boolean isEveryOneSame(String one) {        String[] args = one.split("-");        if (args[0].equals(args[1])) {            return true;        }        return false;    }// 條件1private boolean getStrCount(String str) {String[] args = str.split("-");int blueCount = 0;int redCount = 0;for (int i = 0; i < args.length; i++) {if (args[i].equals("藍")) {blueCount++;} else if (args[i].equals("紅")) {redCount++;}}if (blueCount > 4 || redCount > 4) {return false;}return true;}


可能的組合就剩下了下面幾種了。


6: 藍-藍 紅-紅 紅-藍8: 藍-藍 紅-藍 紅-紅9: 藍-藍 紅-藍 紅-藍12: 紅-紅 藍-藍 紅-藍16: 紅-紅 紅-藍 藍-藍18: 紅-紅 紅-藍 紅-藍20: 紅-藍 藍-藍 紅-紅21: 紅-藍 藍-藍 紅-藍22: 紅-藍 紅-紅 藍-藍24: 紅-藍 紅-紅 紅-藍25: 紅-藍 紅-藍 藍-藍26: 紅-藍 紅-藍 紅-紅27: 紅-藍 紅-藍 紅-藍


可以排除編號2,4,5,10,11,13六種情況。還剩13種。


條件3.上面的情況中,要排除C可以根據A,B的不知道,然後可以一眼就能看出自己是什麼牌組合。


這種情況就是A手中的牌顏色是一樣的,B手中的牌顏色也是一樣的。例如6和12


public void group() {String[] arg = { "藍-藍", "紅-紅", "紅-藍" };int size = arg.length;int index = 0;for (int i = 0; i < size; i++) {String A = arg[i];for (int j = 0; j < size; j++) {String B = arg[j];for (int k = 0; k < size; k++) {String C = arg[k];index++;String groupStr = String.format("%s %s %s", A, B, C);// 條件1String group = String.format("%s-%s-%s", A, B, C);if (!getStrCount(group))continue;// 條件2if (isEveryOneSame(A) && isEveryOneSame(B)&& isEveryOneSame(C))continue;// 條件3if (isEveryOneSame(A) && isEveryOneSame(B))continue;System.out.print(index + ": ");System.out.println(groupStr);}}}}// 條件2private boolean isEveryOneSame(String one) {String[] args = one.split("-");if (args[0].equals(args[1])) {return true;}return false;}// 條件1private boolean getStrCount(String str) {String[] args = str.split("-");int blueCount = 0;int redCount = 0;for (int i = 0; i < args.length; i++) {if (args[i].equals("藍")) {blueCount++;} else if (args[i].equals("紅")) {redCount++;}}if (blueCount > 4 || redCount > 4) {return false;}return true;}public static void main(String[] args) {// TODO Auto-generated method stubProblem22 problem = new Problem22();problem.group();}}


還剩下11種情況。


8: 藍-藍 紅-藍 紅-紅9: 藍-藍 紅-藍 紅-藍16: 紅-紅 紅-藍 藍-藍18: 紅-紅 紅-藍 紅-藍20: 紅-藍 藍-藍 紅-紅21: 紅-藍 藍-藍 紅-藍22: 紅-藍 紅-紅 藍-藍24: 紅-藍 紅-紅 紅-藍25: 紅-藍 紅-藍 藍-藍26: 紅-藍 紅-藍 紅-紅27: 紅-藍 紅-藍 紅-藍

得出結果


上面剩下的11中情況都是符合實際的拿牌情況,以及根據A,B,C第一輪都無法判斷出自己手中的牌這些條件過濾後的組合。那麼再根據最後一個第二輪A就已經知道自己的牌了。說明從上面組合中找出,以B,C組合為關鍵字的,A只有一種情況的組合。比如情況8中,B,C組合是“紅-藍 紅-紅”,那麼根據這個去找找看,同樣是這個條件的A還有沒有其他情況。很顯然發現了第26號符合。說明這種組合是不符合要求的。而第20號的“藍-藍 紅-紅”只有一種情況,說明符合要求。那用程式怎麼實現,我們可以以B+C為關鍵字組建一個map,value值為這個關鍵字在上面11情況中出現的次數。這樣我們可以得到出現一次的關鍵字,這樣很容易確定是第幾號。


public class Problem22 {    //以BC為關鍵字,次數為value的MAP    Map<String,Integer> map = new LinkedHashMap<String,Integer>();    //以BC為關鍵字,組合為value的MAP    Map<String,String> map1 = new LinkedHashMap<String,String>();    public void group() {        String[] arg = { "藍-藍", "紅-紅", "紅-藍" };        int size = arg.length;        int index = 0;        for (int i = 0; i < size; i++) {            String A = arg[i];            for (int j = 0; j < size; j++) {                String B = arg[j];                for (int k = 0; k < size; k++) {                    String C = arg[k];                    index++;                    String groupStr = String.format("%s %s %s", A, B, C);                    // 條件1                    String group = String.format("%s-%s-%s", A, B, C);                    if (!getStrCount(group))                        continue;                    // 條件2                    if (isEveryOneSame(A) && isEveryOneSame(B)                            && isEveryOneSame(C))                        continue;                    // 條件3                    if (isEveryOneSame(A) && isEveryOneSame(B))                        continue;                    if(map.containsKey(B + C)){                       int num =  map.get(B+C);                       map.put(B+C,++num);                    }else{                        map.put(B+C,1);                    }                    map1.put(B+C,index + ": "+groupStr);                    System.out.print(index + ": ");                    System.out.println(groupStr);                }            }        }        Set<Map.Entry<String, Integer>> entrys = map.entrySet();        Iterator<Map.Entry<String, Integer>> iter = entrys.iterator();        //找到次數為1的組合        while(iter.hasNext()){            Map.Entry<String, Integer> entry= iter.next();            if(entry.getValue() ==1){                String answer = map1.get(entry.getKey());                System.out.println("從上面的組合中找到的合格答案為 : "+answer);            }        }    }    // 條件2    private boolean isEveryOneSame(String one) {        String[] args = one.split("-");        if (args[0].equals(args[1])) {            return true;        }        return false;    }    // 條件1    private boolean getStrCount(String str) {        String[] args = str.split("-");        int blueCount = 0;        int redCount = 0;        for (int i = 0; i < args.length; i++) {            if (args[i].equals("藍")) {                blueCount++;            } else if (args[i].equals("紅")) {                redCount++;            }        }        if (blueCount > 4 || redCount > 4) {            return false;        }        return true;    }    public static void main(String[] args) {        // TODO Auto-generated method stub        Problem22 problem = new Problem22();        problem.group();    }}

結果為


8: 藍-藍 紅-藍 紅-紅9: 藍-藍 紅-藍 紅-藍16: 紅-紅 紅-藍 藍-藍18: 紅-紅 紅-藍 紅-藍20: 紅-藍 藍-藍 紅-紅21: 紅-藍 藍-藍 紅-藍22: 紅-藍 紅-紅 藍-藍24: 紅-藍 紅-紅 紅-藍25: 紅-藍 紅-藍 藍-藍26: 紅-藍 紅-藍 紅-紅27: 紅-藍 紅-藍 紅-藍從上面的組合中找到的合格答案為 : 20: 紅-藍 藍-藍 紅-紅從上面的組合中找到的合格答案為 : 21: 紅-藍 藍-藍 紅-藍從上面的組合中找到的合格答案為 : 22: 紅-藍 紅-紅 藍-藍從上面的組合中找到的合格答案為 : 24: 紅-藍 紅-紅 紅-藍


有4種情況下,A可以猜出自己的牌。當然需要A能有這麼強的邏輯。


總結


有沒有發現可能的情況中A  手中的牌都是一樣的:紅藍。所以以後你就猜自己是紅藍就行了吧。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.