interviewstreet - Grid Walking 动态规划

题目来源:https://www.interviewstreet.com/challenges/dashboard/#problem/4e48bfab1bc3e

解题报告:

首先计算组合值C[m][n],按照公式C[m][n] = C[m-1][n-1] + C[m-1][n]获得。

f[i][j][k],代表第i维,位于位置j时,走k步有几种走法。

则有方程f[i][j][k] = f[i][j-1][k-1] + f[i][j+1][k-1],考虑j-1<=0, j+1>D[i]的情况

path[i]k],代表只变化第0维到第i维,走k步,有几种走法。

则有path[0][k] = f[0][X[0]][k], 1<= k <= M

且path[i][k] = SUM ( C[k][j] * path[i-1][j] * f[i][X[i]][k-j] ) , 对每个j, 0<= j <= k

最后输出path[N-1][M]。

这题的关键在于大数据!!!,所以用long long,然后在每个地方加 % 1000000007,我因为漏在几个地方加这个,WA了快20次了吧T_T

#include <iostream>
using namespace std;

long long f[10][100][301];
long long path[10][301];
int C[301][301];

int main()
{
    int T;
    cin >> T;
    C[0][0] = 1;
    for (int i = 1; i <= 300; i++)
    {
        C[i][0] = 1;
        C[i][i] = 1;
        for (int j = 1; j < i; j++)
            C[i][j] = (C[i-1][j-1] + C[i-1][j]) % 1000000007;
    }

    while(T-- > 0)
    {
        int N;
        int M;
        cin >> N >> M;
        int *X = new int[N];
        int *D = new int[N];
        
        for (int i = 0; i < N; i++)
        {
            cin >> X[i];
            X[i]--;
        }
        for (int i = 0; i < N; i++)
        {
            cin >> D[i];
        }

        for (int i = 0; i < N; i++)
        {
            for (int k = 0; k <= M; k++)
            {
                path[i][k] = 0;
                for (int j = 0; j < D[i]; j++)
                    f[i][j][k]=0;
            }
        }
        
        for (int i = 0; i < N; i++)
        {
            path[i][0] = 1;
            for (int j = 0; j < D[i]; j++)
                f[i][j][0] = 1;
        }
        
        for (int i = 0; i < N; i++)
        {
            for (int k = 1; k <= M; k++)
            {
                for (int j = 0; j < D[i]; j++)
                {
                    if (j - 1 >= 0)
                    {
                        f[i][j][k] += f[i][j-1][k-1] % 1000000007;
                        f[i][j][k] = f[i][j][k] % 1000000007;
                    }
                    if (j + 1 < D[i])
                    {
                        f[i][j][k] += f[i][j+1][k-1] % 1000000007;
                        f[i][j][k] = f[i][j][k] % 1000000007;
                    }
                    f[i][j][k] = f[i][j][k] % 1000000007;
                }
            }
                        
        }
        for (int k = 1; k <= M; k++)
            path[0][k] = f[0][X[0]][k];
        
        for (int i = 1; i < N; i++)
        {
            for (int k = 1; k <= M; k++)
            {
                path[i][k] = 0;
                for (int j = 0; j <= k; j++)
                {
                    path[i][k] += ((C[k][j] * (path[i-1][j] % 1000000007)) % 1000000007)  * (f[i][X[i]][k-j] % 1000000007) % 1000000007;
                    path[i][k] = path[i][k] % 1000000007;
                }
            }
        }
        cout << path[N-1][M] % 1000000007 << endl;
        delete[] X;
        delete[] D;
    }

}


附录:

Grid Walking (Score 50 points) 
You are situated in an N dimensional grid at position(x_1,x2,...,x_N). The dimensions of the grid are (D_1,D_2,...D_N). In one step, you can walk one step ahead or behind in any one of the N dimensions. (So there are always 2N possible different moves). In how many ways can you take M steps such that you do not leave the grid at any point ? You leave the grid if you for any x_i, either x_i <= 0 or x_i > D_i.

Input:
The first line contains the number of test cases T. T test cases follow. For each test case, the first line contains N and M, the second line contains x_1,x_2...,x_N and the 3rd line contains D_1,D_2,...,D_N.

Output:
Output T lines, one corresponding to each test case. Since the answer can be really huge, output it modulo 1000000007.

Constraints: 1 <= T <= 10
1 <= N <= 10
1 <= M <= 300
1 <= D_i <= 100
1 <= x_i <= D_i

Sample Input #00:
10
1 287
44
78
1 236
25
87
1 122
41
63
1 260
7
64
1 127
3
73
1 69
6
68
1 231
14
63
1 236
13
30
1 259
38
70
1 257
11
12
Sample output: 
38753340
587915072
644474045
423479916
320130104
792930663
846814121
385120933
60306396
306773532



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值