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

POJ 3254 Corn Fields:狀壓 DP 解決放牛問題

     編輯:C++ 入門

POJ 3254 Corn Fields:狀壓 DP 解決放牛問題

n 行 m 列草地(m≤12),1 表可放牧,0 不可。牛放在可放牧格,且任兩牛不可相鄰(上下左右)。求放牛方案數模 1e8。

狀態壓縮

每行狀態用 m 位二進制數表示:1=放牛,0=不放。合法狀態滿足:

  1. 無相鄰 1:(s & (s<<1)) == 0。
  2. 僅在可放牧格:(s & ~grass_row) == 0,即 (s & forbidden) == 0。輸入 1=可放,取反得 forbidden。

預計算所有合法狀態存入 status[],數量 ≤ F_{m+2} (m=12 時 377)。

DP 轉移

dp[i][s] = 前 i 行,第 i 行狀態為 s 的方案數。轉移:

for (int i=1; i

完整代碼 (C++)

const int MOD = 100000000;
int grass[15], status[1<<12], dp[15][1<<12];

int main() {
    int n, m;
    while (scanf("%d%d", &n, &m) == 2) {
        memset(grass, 0, sizeof(grass));
        for (int i=0; i

Java 版本要點

  • 用 Scanner 讀入,System.out.println 輸出。
  • 數組大小同 C++,邏輯完全一致。

關鍵優化

  1. 預篩選合法狀態,減少轉移枚舉量(377 vs 4096)。
  2. 草地取反存儲,直接 & 判衝突。
  3. 模 1e8 非質數,僅用加法取模。

複雜度

  • 狀態數 S ≤ 377,行數 n ≤ 12(實際 n 可能更大,但 m≤12)。
  • 轉移 O(n × S²) ≈ 12 × 14e4 = 1.7e6,極快。

此題是「狀壓 DP 行狀態轉移」的標準模板,適用於網格放置、不相鄰、依賴上一行的計數問題。

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