三角網格 10 個點,9 個小三角形。雙方輪流畫邊,畫完某三角形第 3 條邊者佔有該三角形並獲得額外一步。給定已畫邊序列,雙方最優策略下誰贏?
state,1 表示已畫tri[9][3]score:先手佔有三角形數 - 後手佔有數dfs(state, score) 返回當前玩家在狀態 state 下,分數差為 score 時的最優分數差(當前玩家視角)。
ee 後新增三角形數 gaingain > 0:獲得額外回合,遞歸 dfs(newState, score + gain),結果為 gain + 子結果gain == 0:換對手,遞歸 dfs(newState, score),結果為 -子結果(零和博弈)int dp[1<<18], tri[9][3] = {...}; // 預存三角形邊索引
int dfs(int state, int score) {
if (dp[state] != -1) return dp[state];
int best = -INF;
for (int e = 0; e < 18; ++e) if (!(state & (1<<e))) {
int nstate = state | (1<<e);
int gain = 0;
for (int t = 0; t < 9; ++t) {
int cnt = 0;
for (int k = 0; k < 3; ++k) if (nstate & (1<<tri[t][k])) ++cnt;
if (cnt == 3 && !(state & (1<<tri[t][0])) // 剛好這步完成
&& !(state & (1<<tri[t][1]))
&& !(state & (1<<tri[t][2]))) ++gain;
}
int val = (gain > 0) ? gain + dfs(nstate, score + gain)
: -dfs(nstate, score);
best = max(best, val);
}
return dp[state] = best;
}
讀入已畫邊構造初始 state,計算初始 score(模擬已走步驟)。調用 dfs(state, score),返回值 > 0 先手贏,< 0 後手贏。
dp[state] 記憶化,避免重複計算gain 計算max 對應極大化己方優勢mp[i][j]