3.11~Walking on Grids

转载注明出处 http://www.cnblogs.com/ligun123/archive/2013/03/13/2957938.html
原题:https://www.hackerrank.com/challenges/walking-on-grids

Walking on Grids

There is a N * N matrix. At first you are at the upper left corner (0,0) and you want to get to the lower right corner (N - 1, N - 1). You can only walk down and right.

Futhermore, you can not pass the main diagonal. This means that you can only walk in the upper half or lower half of the matrix (including the diagonal).

Please calcuate How many ways can you get to the end point?

Input

The test case contains only one interger N. (1 <= N <= 2000)

Output

Output the number of the number of ways you can get to the lower right corner without passing the diagonal in a single line. Since the result may be very large, just output the remainder of the answer divided by 10007 please.

Sample Input

4

Sample Output

10

怎么解?关键在于“You can only walk down and right.”和“you can not pass the main diagonal.”

解法一:递归暴力求解,时间复杂度为o(2^n)太暴力了没一点技术含量不可取,先上代码

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

/*
 解题关键在于“You can only walk down and right.”和“you can not pass the main diagonal.”
 通往对角线上的一点的路线,无论从左下半边还是从右上半边,路线数目是一样的,所以计算出左下或者右上半边的数目再乘以2,便是总数目
 */

/*
从(0,0)出发到任一一点的路径数N(x,y)= N(x-1,y)+N(x,y-1),且N(0, y)==1;当只有一个格子(N==1)的时候N(0,0)==1;暴力解法用递归可计算出解,不过效率实在是有点。。。
*/

uint64_t WaysOf(uint16_t x, uint16_t y);     //左下角区域中,返回横向x, 纵向y的路线数目
uint64_t WaysOf(uint64_t n);

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    uint64_t N = 0;
    while (cin>>N) {
        if (N == 0) {
            printf("you have stoped the program!\n");
            break;
        }
        printf("ways : %lld\n", WaysOf(N) % 10007);
    }
    
    return 0;
}

uint64_t WaysOf(uint64_t n)
{
    if (n < 1) {
        return 0;
    }
    else if (n == 1) {
        return 1;
    } else {
        return 2 * WaysOf(n -1, n -1);
    }
}

uint64_t WaysOf(uint16_t x, uint16_t y)
{
    if (x == 0) {
        return 1;
    }
    else if (x == y) {
        //此点在对角线上
        return WaysOf(x -1, y);
    } else {
        return WaysOf(x -1, y) + WaysOf(x, y -1);
    }
}

 解法2:动态规划求解,时间复杂度O(n^2)

uint64_t ways(uint64_t N);      //动态规划

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    uint64_t N = 0;
    while (cin>>N) {
        if (N == 0) {
            break;
        }
        cout<<ways(N) % 10007<<endl;
    }
    
    return 0;
}


/*
 解法二:动态规划
 */

uint64_t ways(uint64_t N)
{//N >= 1 && N <= 2000
    if (N == 1) {
        return 1;
    } else {
        uint64_t value = 0;
        uint64_t *array = (uint64_t *)calloc(N * N, sizeof(uint64_t));    //用一维数组来模拟二维数组存储
        for (uint64_t i = 0; i < N; i++) {
            for (uint64_t j = 0; j <= i; j++) {
                if (j == 0) {
                    array[j + i * N] = 1;
                } else {
                    array[j + i * N] = (array[(j-1) + i * N] + array[j + (i - 1) * N]) % 10007;
                }
            }
        }
        value = array[N * N -1];
        
        /*/
        //printf
        for (uint64_t i = 0; i < N; i++) {
            printf("\n");
            for (uint64_t j = 0; j < N; j++) {
                printf("%lld   ",array[j + i * N]);
            }
        }
        printf("\n************************");
        //*/
        free(array);
        return value * 2;
    }
}

原文地址:https://www.cnblogs.com/ligun123/p/2957938.html