1. 程式人生 > >[JZOJ 2938] 分割田地 {動態規劃}

[JZOJ 2938] 分割田地 {動態規劃}

題目

Description

地主某君有一塊由2×n個柵格組成的土地,有k個兒子,現在地主快要終老了,要把這些土地分給這些兒子。 分給每個兒子的土地最小的單位是一個柵格,同時,分給同一個兒子的土地要求要相鄰連續的。 地主覺得分給某個兒子的土地面積至少有一個柵格,但是具體多少可以隨意。 請問,聰明的你,能夠算出地主一共有多少種分土地的方法嗎?也就是說要求把2*n的柵格分成k個連通區域,每個區域至少有一個柵格。

Input

包含兩個正整數n和k。

Output

包含一個整數,為可以分土地的方法數模100000007。

結題思路

  • f[i][k][0/1]f[i][k][0/1]表示已經取了第1
    i1~i
    行,分為kk個連通區域,狀態為0011時的總方案數
  • 對於狀態0/10/1,我們有如下定義:
  • [1][1]、狀態00表示第ii行的兩個柵格分屬於兩個不同的連通區域
  • [2][2]、狀態11表示第ii行的兩個柵格屬於同一個連通區域

程式碼

#include<cstdio>
using namespace std; 
const int myself=100000007;
int n,k,f[1005][2501][2]; 
inline int minn(int x,int y){return x<y?x:y;}
inline int read()
{
int p=0; char
c=getchar(); while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') p=(p<<3)+(p<<1)+c-'0',c=getchar(); return p; } int main() { n=read(),k=read(); f[1][2][0]=f[1][1][1]=1; for (int i=2;i<=n;i++) for (int j=1;j<=minn(i<<1,k);j++) { f[i][j][0]+=f[i-1
][j-2][0]+f[i-1][j-2][1]+(f[i-1][j-1][0]<<1)+(f[i-1][j-1][1]<<1)+f[i-1][j][0]; f[i][j][1]+=f[i-1][j-1][0]+f[i-1][j-1][1]+(f[i-1][j][0]<<1)+f[i-1][j][1]; f[i][j][0]%=myself; f[i][j][1]%=myself; } printf("%d",(f[n][k][1]+f[n][k][0])%myself); }