【POJ3254】Corn Fields
阿新 • • 發佈:2017-10-04
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