[JZOJ 2938] 分割田地 {动态规划}

版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/83240414


题目

Description

地主某君有一块由2×n个栅格组成的土地,有k个儿子,现在地主快要终老了,要把这些土地分给这些儿子。
分给每个儿子的土地最小的单位是一个栅格,同时,分给同一个儿子的土地要求要相邻连续的。
地主觉得分给某个儿子的土地面积至少有一个栅格,但是具体多少可以随意。
请问,聪明的你,能够算出地主一共有多少种分土地的方法吗?也就是说要求把2*n的栅格分成k个连通区域,每个区域至少有一个栅格。

Input

包含两个正整数n和k。

Output

包含一个整数,为可以分土地的方法数模100000007。


结题思路

思路的源泉——“一篇好博客”

  • f [ i ] [ k ] [ 0 / 1 ] f[i][k][0/1] 表示已经取了第 1   i 1~i 行,分为 k k 个连通区域,状态为 0 0 1 1 时的总方案数
  • 对于状态 0 / 1 0/1 ,我们有如下定义:
  • [ 1 ] [1] 、状态 0 0 表示第 i i 行的两个栅格分属于两个不同的连通区域
  • [ 2 ] [2] 、状态 1 1 表示第 i i 行的两个栅格属于同一个连通区域

代码

#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); 
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/83240414
今日推荐