1. 程式人生 > >【POJ3254】Corn Fields

【POJ3254】Corn Fields

out for ++ pac field 所有 con false urn

http://poj.org/problem?id=3254

題意:給你一塊n*m(0<n,m<=12)的地圖,其中有的方格是肥沃的(用1表示),有的方格是貧瘠的(用0表示)。現在約翰要在肥沃的土地上放奶牛,且要求不能有兩個奶牛相鄰,請問有多少種方案數。

狀壓DP入門題。

首先預處理每一行不考慮貧瘠地時所有可行的放置狀態,用states數組存著。

然後令f(i,j)為考慮前i行且第i行放置狀態為states[j]時的方案數,可得f(i, j)=sigma{f(i-1, k) | states[j]&states[k]==0} (states[j]不包含第j行的貧瘠地),f(i, j)=0(states[j]包含第j行的貧瘠地)。

先計算第一行的方案數,再遞推第二行到第n行的方案數,最後答案為sigma{f(n,j)}。具體實現看代碼

#include <iostream>
#include <vector>
using namespace std;
template <class T>
void update(T &x)
{
    while (x >= 100000000)
        x -= 100000000;
}
int r, c, map[13];            // 初始地圖
int states[1 << 13], siz = 0; // 不考慮貧瘠地時每一行的所有可行放置方案
int dp[13][1 << 13]; // dp[i][j]表示考慮前i行且第i行放置狀態為states[j]時的方案數 int main() { ios::sync_with_stdio(false); cin >> r >> c; for (int i = 0; i < 1 << c; i++) if (!(i & (i << 1))) // 若狀態i不存在兩個相鄰的1 states[++siz] = i; int a;
for (int i = 1; i <= r; i++) { for (int j = 0; j < c; j++) { cin >> a; if (!a) map[i] |= (1 << j); } } for (int i = 1; i <= siz; i++) if (!(states[i] & map[1])) // 若狀態states[i]不包含第一行的貧瘠地,則出現一種放置方案 dp[1][i] = 1; for (int i = 2; i <= r; i++) { for (int j = 1; j <= siz; j++) // 枚舉這一行的放置方案 { if (states[j] & map[i]) // 若狀態states[j]包含第i行的貧瘠地 continue; for (int k = 1; k <= siz; k++) // 枚舉上一行的放置方案 { if (states[k] & states[j]) // 若狀態states[k]與狀態states[j]有相同位置的1 continue; update(dp[i][j] += dp[i - 1][k]); } } } int ans = 0; for (int i = 1; i <= siz; i++) update(ans += dp[r][i]); cout << ans; return 0; }

【POJ3254】Corn Fields