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

NYOD 832 合並遊戲:狀態壓縮 DP

     編輯:關於C++

題目大意

n 個石子(n ≤ 10),給定 n×n 矩陣 A[i][j] 表示合並石子 i 和 j 獲得的金幣(j 消失)。求合並所有石子(剩 1 個)的最大金幣數。

狀態壓縮 DP

用二進制掩碼 mask 表示當前剩餘石子集合(1 為存在,0 為已合並消失)。初始狀態 (1<,目標狀態任意單一位(或 0)。

  • dp[mask]:從狀態 mask 繼續合並到結束的最大金幣數。
  • 遞歸 + 記憶化:枚舉當前 mask 中的每個石子 i 作為「被合並消失」的那個,枚舉與其合並的另一石子 j(j 也在 mask 中),獲得金幣 A[j][i],新狀態 mask ^ (1<。
  • 轉移:dp[mask] = max_{i∈mask, j∈mask, j≠i} (dp[mask^(1<。
  • 基礎情況:dp[0] = 0(或單石子狀態 dp=0)。

代碼實現

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 15;
const int MAXS = 1<<10; // 1024

int n;
int A[MAXN][MAXN];
int dp[MAXS];

int solve(int mask) {
    if (dp[mask] != -1) return dp[mask];
    if (mask == 0) return 0;
    int best = 0;
    for (int i = 0; i < n; i++) if (mask & (1<

複雜度分析

  • 狀態數:2^n ≤ 1024。
  • 每狀態枚舉 O(n²) 轉移,總 O(n² 2^n) ≈ 100 * 1024 = 1e5,極快。
  • 記憶化避免重複計算。

總結

狀態壓縮 DP 經典應用:n ≤ 10 即可用 bitmask 表示集合。關鍵是明確「誰消失、誰獲得金幣」的轉移邏輯,並利用記憶化搜索自頂向下計算。代碼簡潔,是狀壓 DP 入門佳例。

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