USACO 2006 NOV Corn Fields
題目描述
Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can‘t be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.
Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.
農場主John新買了一塊長方形的新牧場,這塊牧場被劃分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一塊正方形的土地。John打算在牧場上的某幾格裏種上美味的草,供他的奶牛們享用。
遺憾的是,有些土地相當貧瘠,不能用來種草。並且,奶牛們喜歡獨占一塊草地的感覺,於是John不會選擇兩塊相鄰的土地,也就是說,沒有哪兩塊草地有公共邊。
John想知道,如果不考慮草地的總塊數,那麽,一共有多少種種植方案可供他選擇?(當然,把新牧場完全荒廢也是一種方案)
輸入輸出格式
輸入格式:第一行:兩個整數M和N,用空格隔開。
第2到第M+1行:每行包含N個用空格隔開的整數,描述了每塊土地的狀態。第i+1行描述了第i行的土地,所有整數均為0或1,是1的話,表示這塊土地足夠肥沃,0則表示這塊土地不適合種草。
輸出格式:一個整數,即牧場分配總方案數除以100,000,000的余數。
輸入輸出樣例
輸入樣例#1:2 3 1 1 1 0 1 0輸出樣例#1:
9
分析
數據大小已經很明顯的提示,這題是狀壓DP啊!
讀入以後,我們用F[i]來表示第i行上的草地情況,這裏F數組裏的是二進制數。MAXSTATE是2n,也就是這道題的最大狀態(n列都是1)。
然後我們在0~MAXSTATE-1這些狀態裏找到合法狀態,也就是不能兩頭牛的草地是相鄰的。判斷方法就是把這個二進制數左移一位and,然後右移一位and。如果這個狀態是合法的,那麽都應該返回0。
然後就開始動規,從第一行開始,在每行裏找所有狀態,如果這個狀態是合法的,且不會在貧瘠的草地上(和(j & F[i]) == j說明沒有草地種在貧瘠的地方),那麽接下來開始找上一行的合法情況(上下兩行之間沒有相鄰的草地),把上一行的情況數加到f[i][j]裏。
最後把最下面一行的每一列的情況書統統加起來,就是答案啦~
程序
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int M = 1e9; 4 int m, n, f[13][4096], F[13], field[13][13]; 5 // max state: (11111111111)2 = (4095)10 6 bool state[4096]; 7 int main() 8 { 9 cin >> m >> n; 10 for (int i = 1; i <= m; i++) 11 for (int j = 1; j <= n; j++) 12 cin >> field[i][j]; 13 for (int i = 1; i <= m; i++) 14 for (int j = 1; j <= n; j++) 15 F[i] = (F[i] << 1) + field[i][j]; 16 // F[i]: state on line i 17 int MAXSTATE = 1 << n; 18 for (int i = 0; i < MAXSTATE; i++) 19 state[i] = ((i&(i<<1))==0) && ((i&(i>>1))==0); 20 f[0][0] = 1; 21 for (int i = 1; i <= m; i++) 22 for (int j = 0; j < MAXSTATE; j++) 23 if (state[j] && ((j & F[i]) == j)) 24 for (int k = 0; k < MAXSTATE; k++) 25 if ((k & j) == 0) 26 f[i][j] = (f[i][j] + f[i-1][k]) % M; 27 int ans = 0; 28 for (int i = 0; i < MAXSTATE; i++) 29 ans += f[m][i], ans %= M; 30 cout << ans << endl; 31 getchar(); 32 getchar(); 33 return 0; 34 }
USACO 2006 NOV Corn Fields