HDU 4301 Divide Chocolate(打表+dp)

Divide Chocolate

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description
It is well known that claire likes dessert very much, especially chocolate. But as a girl she also focuses on the intake of calories each day. To satisfy both of the two desires, claire makes a decision that each chocolate should be divided into several parts, and each time she will enjoy only one part of the chocolate. Obviously clever claire can easily accomplish the division, but she is curious about how many ways there are to divide the chocolate.
这里写图片描述
To simplify this problem, the chocolate can be seen as a rectangular contains n*2 grids (see above). And for a legal division plan, each part contains one or more grids that are connected. We say two grids are connected only if they share an edge with each other or they are both connected with a third grid that belongs to the same part. And please note, because of the amazing craft, each grid is different with others, so symmetrical division methods should be seen as different.

Input
First line of the input contains one integer indicates the number of test cases. For each case, there is a single line containing two integers n (1<=n<=1000) and k (1<=k<=2*n).n denotes the size of the chocolate and k denotes the number of parts claire wants to divide it into.

Output
For each case please print the answer (the number of different ways to divide the chocolate) module 100000007 in a single line.

Sample Input
2
2 1
5 2

Sample Output
1
45

题目大意:
把一个2×n的巧克力能分成多少部分

题目分析:
这里把我分析的过程将一下应该就能明白了,首先我是把巧克力看成2×n的矩阵,n一定的话,分出来的结果肯定就是一样的,所以我觉得先打表,然后直接输出。接下来我想的是随着n的增大,每多一列,结果可以根据之前的分法推理出来,也就是递推,所以自然而然的想到了dp,所以接下来的任务也就是怎么找状态转移方程了
我最开始是这样定义的
dp[i][j]:表示前i列巧克力分成j份的分法
我们这样想,第i列可以单独拿出0,1,2块巧克力,分别考虑:
①第i列分出来两小块巧克力:那么dp[i][j]=dp[i-1][j-2];
②第i列分出来一块巧克力:分出来一块的话有两种分法,一种是两小块作为一大块,另外一种的话是一小块跟前i-1块连在一起,另外一小块单独拿出,这样dp[i][j]=3*dp[i-1][j-1];
③第i列的巧克力全部连接在前i-1列上:这时有两种情况
1)第i列的两小块连着:
如果第i-1列的两小块巧克力连着,那么dp[i][j]=dp[i-1][j]
如果第i-1列的两小块巧克力分着,第i列的这个整体连接在第i-1列的哪块巧克力上都行,所以dp[i][j]=2×dp[i-1][j]
2)第i列的两小块分着
如果第i-1列的两小块巧克力连着,那么不存在第i列的两小块分着的情况;
如果第i-1列的两小块巧克力分着,那么dp[i][j]=dp[i-1][j]
综上来看,对于③的递推关系,与第i-1列的两块巧克力的分与合有着关系,但是这一关系并未在dp的矩阵当中体现出来,来看数据规模,n只有1000,所以我们再添加一维来记录分与合就可以了,只要细心分一下就没问题。接下来看代码吧。
代码:

#include "stdio.h"
#define MOD 100000007
int dp[1000+5][2000+5][2];//dp[i][j][0]表示第第i列两块连着
int main()
{
    //打表
    for (int i = 1; i <=1000; i++)
    {
        for(int j=1;j<=2*i;j++)
        {
            if(j==1){
                dp[i][j][0]=1;//一个整体的话第i列的两块不可能分开
            }else if(j==2*i){
                dp[i][j][1]=1;//这种情况表示全都拆散了
            }else{
            //第i列连着,然后再讨论第i-1列的连接与否进行递推
                dp[i][j][0]=(dp[i-1][j-1][0]+dp[i-1][j-1][1]+dp[i-1][j][0]+2*dp[i-1][j][1])%MOD;
            //第i列分着,再进行讨论
                dp[i][j][1]=(dp[i-1][j-2][0]+dp[i-1][j-2][1]+2*dp[i-1][j-1][0]+2*dp[i-1][j-1][1]+dp[i-1][j][1])%MOD;
            }           
        }
    }
    int t,n,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        printf("%d\n",(dp[n][k][0]+dp[n][k][1])%MOD);
    }
    return 0;
}

如果有任何问题或者是有更好的方法,请及时留言

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值