首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 邏輯推理:乒乓球隊比賽名單排列組合

     編輯:Java 相關知識

問題描述

甲隊 a,b,c vs 乙隊 x,y,z。a 不和 x 比,c 不和 x,z 比。求三對比賽配對。

約束條件形式化

  • 對手各不相同 (一一對應)
  • a ≠ x
  • c ≠ x, c ≠ z → c = y

邏輯推導

  1. c 只能對 y
  2. 剩下 a,b 對 x,z
  3. a 不能對 x → a 對 z
  4. b 對 x

唯一解:a-z, b-x, c-y

原始代碼分析 (暴力枚舉)

String[] op = {"x", "y", "z"};
ArrayList list = new ArrayList<>();

for (int i = 0; i < 3; i++)      // a 的對手
    for (int j = 0; j < 3; j++)  // b 的對手
        for (int k = 0; k < 3; k++) { // c 的對手
            PingPang p = new PingPang(op[i], op[j], op[k]);
            if (!p.a.equals(p.b) && !p.b.equals(p.c) && !p.a.equals(p.c)  // 對手互不相同
                && !p.a.equals("x")  // a ≠ x
                && !p.c.equals("x") && !p.c.equals("z")) {  // c ≠ x,z
                list.add(p);
            }
        }

代碼優化點

  • 三重循環 27 次迭代,可接受但非最優
  • 條件判斷順序可優化:先判斷 c == 'y' 直接確定
  • 用 Set 判斷對手唯一性更清晰

優化版本:邏輯推導 + 驗證

import java.util.*;

public class PingPangLogic {
    public static void main(String[] args) {
        // 1. 邏輯推導
        char cOpp = 'y';  // c 只能對 y
        char aOpp, bOpp;
        
        // a 不能對 x,且不能對 y (被 c 佔用) → a 必須對 z
        aOpp = 'z';
        // b 對剩下的 x
        bOpp = 'x';
        
        // 2. 驗證
        Set opponents = new HashSet<>(Arrays.asList(aOpp, bOpp, cOpp));
        if (opponents.size() == 3 && aOpp != 'x' && cOpp != 'x' && cOpp != 'z') {
            System.out.printf("a-%c, b-%c, c-%c%n", aOpp, bOpp, cOpp);
        }
        
        // 3. 通用暴力枚舉 (擴展性更強)
        bruteForce();
    }
    
    static void bruteForce() {
        char[] teamB = {'x', 'y', 'z'};
        for (char a : teamB) {
            if (a == 'x') continue;  // a ≠ x
            for (char b : teamB) {
                if (b == a) continue;  // 對手唯一
                for (char c : teamB) {
                    if (c == a || c == b) continue;
                    if (c == 'x' || c == 'z') continue;  // c ≠ x,z
                    System.out.printf("枚舉解: a-%c, b-%c, c-%c%n", a, b, c);
                }
            }
        }
    }
}

回溯算法通用框架 (擴展至 N 人)

void backtrack(int idx, char[] teamA, char[] teamB, boolean[] used, char[] match) {
    if (idx == teamA.length) {
        printMatch(teamA, match);
        return;
    }
    for (int i = 0; i < teamB.length; i++) {
        if (!used[i] && checkConstraints(teamA[idx], teamB[i])) {
            used[i] = true;
            match[idx] = teamB[i];
            backtrack(idx + 1, teamA, teamB, used, match);
            used[i] = false;
        }
    }
}

boolean checkConstraints(char aPlayer, char bPlayer) {
    if (aPlayer == 'a' && bPlayer == 'x') return false;
    if (aPlayer == 'c' && (bPlayer == 'x' || bPlayer == 'z')) return false;
    return true;
}

總結

本題核心是約束滿足問題 (CSP)。小規模 (3×3) 暴力枚舉即可;大規模需回溯 + 剪枝 + 启發式 (如最少剩餘值啟發式)。邏輯推導能瞬間得出唯一解,展示了「思考勝過編碼」的原則。Java 實現中,Set 去重、Stream 處理、回溯框架是可遷移技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved