Hrbust 1327 合唱【dp】

合唱
Time Limit: 1000 MSMemory Limit: 65536 K
Total Submit: 30(15 users)Total Accepted: 19(13 users)Rating: Special Judge: No
Description

Leyni要组织一场合唱,有x个男生和y个女生要参加,Leyni要将他们排成一行,要求最多可以将a个男生连续排在一起,最多将b个女生连续排在一起。我们假设所有的男生之间是没有区别的,所有的女生之间也是没有区别的,而且这x + y个人都必须参加合唱。

Leyni想知道不同的方案总数除以1000000007的余数。

Input

本题有多组测试数据,输入的第一行是一个整数T代表着测试数据的数量,接下来是T组测试数据。

对于每组测试数据:

1 包含四个以空格分隔的整数xya(1 ≤ x, y ≤ 100, 1 ≤ a, b ≤ 10)

Output

对于每组测试数据:

1 输出方案总数除以1000000007的余数。

Sample Input

2

2 3 1 2

2 4 1 1

Sample Output

5

0

Hint

第一组样例的五种方案为:男女男女女,男女女男女,女男女男女,女男女女男,女女男女男。

Source
哈理工2012春季校赛热身赛 2012.04.03
Author
齐达拉图@HRBUST

思路:


1、统计方案数,考虑dp,设定dp【i】【j】【2】:

①dp【i】【j】【0】表示长度为i的队列中,以男生结尾,并且一共有j个男生的方案数。

②dp【i】【j】【0】表示长度为i的队列中,以女生结尾,并且一共有j个男生的方案数。

那么ans=dp【n】【x】【0】+dp【n】【x】【1】;


2、其状态转移方程也不是很难写出:
①dp【i】【j】【0】+=dp【i-l】【j-l】【1】;表示在以女生结尾的序列之后,加上连续的l个男生。(1<=l<=a)

②dp【i】【j】【1】+=dp【i-l】【j】【0】;表示在以男生结尾的序列之后,加上连续的l个女生。(1<=l<=b)


3、注意数组不要越界以及取模问题。


Ac代码:


#include<stdio.h>
#include<string.h>
using namespace std;
#define ll long long int
#define mod 1000000007
ll dp[205][105][2];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int x,y,a,b;
        scanf("%d%d%d%d",&x,&y,&a,&b);
        int n=x+y;
        memset(dp,0,sizeof(dp));
        dp[0][0][0]=1;
        dp[0][0][1]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=x&&j<=i;j++)
            {
                for(int l=1;l<=a;l++)
                {
                    if(j-l>=0)
                    dp[i][j][0]+=dp[i-l][j-l][1];
                    dp[i][j][0]%=mod;
                }
                for(int l=1;l<=b;l++)
                {
                    if(i-l>=0)
                    dp[i][j][1]+=dp[i-l][j][0];
                    dp[i][j][1]%=mod;
                }
            }
        }
        ll output=(dp[n][x][0]+dp[n][x][1])%mod;
        printf("%lld\n",output);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值