農場主john新買了一塊長方形的新牧場,這塊牧場被劃分成m行n列(1 ≤ m ≤ 12; 1 ≤ n ≤ 12),每一格都是一塊正方形的土地。john打算在牧場上的某幾格里種上美味的草,供他的奶牛們享用。
遺憾的是,有些土地相當貧瘠,不能用來種草。並且,奶牛們喜歡獨佔一塊草地的感覺,於是john不會選擇兩塊相鄰的土地,也就是說,沒有哪兩塊草地有公共邊。
john想知道,如果不考慮草地的總塊數,那麼,一共有多少種種植方案可供他選擇?(當然,把新牧場完全荒廢也是一種方案)
2 31 1 1
0 1 0
看到兩個數m n都小於12,第一反應就是狀壓,用二進位制來表示每一行的狀態,例如,j=13時,j 用二進位制表示為1101,表示1號位置種草,2號位置種草,3號位置不種草,4號位置種草。
首先輸入m n ,然後輸入地圖,這裡有一種快捷方式記錄地圖,相當於把每一行的狀態壓縮為乙個數字儲存,列如樣例第一行1 1 1壓縮為7,這樣會使後面的操作簡單些
for
(int i=
1;i<=m;i++
)for
(int j=
0;j)
本題有兩個約束條件,第一是不能 0 位置種草,第二時不能有連續的草叢
先解決第乙個條件,由於之前已經記錄了壓縮後的地圖狀態了,假設此時第i行地圖狀態為mp[i],第i行的狀態為k, 假設mp[i]二進位制的第j位為0,那麼k的第j位就只能是0,如果mp[i]第j位為1,那麼k的第j位可以是0或1,這裡我們用一種運算——|,或運算
用 (mp[i] | k) == mp[i] 來判斷合法
畫圖理解下
第二個條件比較簡單,設當前行狀態為 j ,上一行狀態為 k
j & ( j >>1 )可以快速判斷是否有連續的 1
j & k 可以快速判斷是否與上一行狀態有衝突
兩個條件都滿足時候 轉移狀態dp[i] [j] += dp[i-1] [l]
附上**
#include
.h>
using namespace std;
int n,m,sum=
0,mod=
1e9;
int mp[
105]
=,dp[13]
[1<<12]
;//mp儲存地圖情況,dp列舉每一種狀況
int main()
for(int l=
0;l<
;l++
)//初始化第一行的情況
for(int i=
2;i<=m;i++)}
}for
(int i=
0;i<
;i++
) cout<
return0;
}
洛谷 1879 玉公尺田
題目描述 農場主john新買了一塊長方形的新牧場,這塊牧場被劃分成m行n列 1 m 12 1 n 12 每一格都是一塊正方形的土地。john打算在牧場上的某幾格里種上美味的草,供他的奶牛們享用。遺憾的是,有些土地相當貧瘠,不能用來種草。並且,奶牛們喜歡獨佔一塊草地的感覺,於是john不會選擇兩塊相鄰...
Luogu P1879玉公尺田(狀壓DP)
題目鏈結 資料範圍這麼小,難度又這麼大,一般就是狀態壓縮dp了。對輸入進行處理,二進位制表示每一行的草地狀況。如111表示這一行草地肥沃,壓縮成7.所以f i j 表示第i行狀態為j時的方案數 狀態j指的是乙個二進位制集合,有牛在吃草的位置是1,不再吃草的位置是0 f i j sum f i 1 k...
P1825 玉公尺田迷宮
有了上次題目看錯的教訓後再不敢隨便看題了usaco太坑,這題絕對不水,傳送門還特別玄學自然 短不了 const z array 1.4,1.2 of 1.1 1,0 0,1 1,0 0,1 var i,j,k longint m,n longint pdx,pdy longint csmx,csmy...