SDNU 1508.F.Feed the monkey(DFS)

Description

Alice has a monkey, she must feed fruit to the monkey every day.She has three kinds of fruits, bananas, 
peaches and apples. Every day, she chooses one in three, and pick one of this to feed the monkey. 
But the monkey is picky, it doesn’t want bananas for more than D1 consecutive days, peaches for more than D2 
consecutive days, or apples for more than D3 consecutive days. Now Alice has N1 bananas, N2 peaches and N3 
apples, please help her calculate the number of schemes to feed the monkey.

Input

 Multiple test cases. The first line contains an integer T (T<=20), indicating the number of test case.
Each test case is a line containing 6 integers N1, N2, N3, D1, D2, D3 (N1, N2, N3, D1, D2, D3<=50).

Output

 One line per case. The number of schemes to feed the monkey during (N1+N2+N3) days.
The answer is too large so you should mod 1000000007.

Sample Input

1
2 1 1 1 1 1

Sample Output

6

Hint

 Answers are BPBA, BPAB, BABP, BAPB, PBAB, and ABPB(B-banana P-peach A-apple)

思路:这是一道思维题,要求的是排列组合问题。解题方式是:一个一个的添加水果,尝试在末尾位置添加不同的水果,看有多少种不同的排列方式。特别要注意的是,这道题对空间有限制,所以定义数组不能太大,否则会MLE。

///
///                            _ooOoo_
///                           o8888888o
///                           88" . "88
///                           (| -_- |)
///                           O  =  /O
///                        ____/`---'\____
///                      .'  \|     |//  `.
///                     /  \|||  :  |||//  
///                    /  _||||| -:- |||||-  
///                    |   | \  -  /// |   |
///                    | \_|  ''---/''  |   |
///                      .-\__  `-`  ___/-. /
///                  ___`. .'  /--.--  `. . __
///               ."" '<  `.___\_<|>_/___.'  >'"".
///              | | :  `- \`.;` _ /`;.`/ - ` : | |
///                 `-.   \_ __ /__ _/   .-` /  /
///         ======`-.____`-.___\_____/___.-`____.-'======
///                            `=---='
///        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
///                      Buddha Bless, No Bug !
///

#include <bits/stdc++.h>
using namespace std;

const int mod = 1000000007;
const int maxn = 55;

int T, n[3], d[3], dp[maxn][maxn][maxn][3][maxn], sum;
int dfs(int n1, int n2, int n3, int t, int m)
{
    if(n1 > n[0] || n2 > n[1] || n3 > n[2] || (n1 + n2 + n3) > sum) return 0;///如果某一种水果的数量已经超过了已有的数量
    if(dp[n1][n2][n3][t][m] != -1) return dp[n1][n2][n3][t][m];///如果dp[n1][n2][n3][t][m]是已经计算过的
    if(t == 0 && m > d[0] || t == 1 && m > d[1] || t == 2 && m > d[2]) return 0;///如果连续的水果已经超过规定的连续天数
    if(n1 + n2 + n3 == sum) return 1;
    int ans = 0;
    ///尝试在水果队列后面加水果,计算排列方式的数量
    if(t == 0)
    {
        ans = (ans + dfs(n1 + 1, n2, n3, 0, m + 1)) % mod;///如果在队列后面加苹果,会有多少种排列方式
        ans = (ans + dfs(n1, n2 + 1, n3, 1, 1)) % mod;///如果在队列后面加香蕉,会有多少种排列方式
        ans = (ans + dfs(n1, n2, n3 + 1, 2, 1)) % mod;///如果在队列后面加桃子,会有多少种排列方式
        return dp[n1][n2][n3][t][m] = ans;
    }
    if(t == 1)
    {
        ans = (ans + dfs(n1 + 1, n2, n3, 0, 1)) % mod;///如果在队列后面加苹果,会有多少种排列方式
        ans = (ans + dfs(n1, n2 + 1, n3, 1, m + 1)) % mod;///如果在队列后面加香蕉,会有多少种排列方式
        ans = (ans + dfs(n1, n2, n3 + 1, 2, 1)) % mod;///如果在队列后面加桃子,会有多少种排列方式
        return dp[n1][n2][n3][t][m] = ans;
    }
     if(t == 2)
    {
        ans = (ans + dfs(n1 + 1, n2, n3, 0, 1)) % mod;///如果在队列后面加苹果,会有多少种排列方式
        ans = (ans + dfs(n1, n2 + 1, n3, 1, 1)) % mod;///如果在队列后面加香蕉,会有多少种排列方式
        ans = (ans + dfs(n1, n2, n3 + 1, 2, m + 1)) % mod;///如果在队列后面加桃子,会有多少种排列方式
        return dp[n1][n2][n3][t][m] = ans;
    }
}

int main()
{
    scanf("%d", &T);
    while(T--)
    {
        int ans = 0;
        scanf("%d%d%d%d%d%d", &n[0], &n[1], &n[2], &d[0], &d[1], &d[2]);
        sum = n[0] + n[1] + n[2];
        memset(dp, -1, sizeof(dp));
        ans = (ans + dfs(1, 0, 0, 0, 1)) % mod;
        ans = (ans + dfs(0, 1, 0, 1, 1)) % mod;
        ans = (ans + dfs(0, 0, 1, 2, 1)) % mod;
        printf("%d
", ans);
    }
    return 0;
}

 

 

 
原文地址:https://www.cnblogs.com/RootVount/p/11236732.html