甲隊 a,b,c vs 乙隊 x,y,z。a 不和 x 比,c 不和 x,z 比。求三對比賽配對。
唯一解: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);
}
}
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);
}
}
}
}
}
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 處理、回溯框架是可遷移技能。