The King's Walk(dp)

题目链接:https://vjudge.net/problem/Kattis-kingswalk https://open.kattis.com/problems/kingswalk

题意:给你 n * n 的棋盘,两个点,从其中一个点开始走,在当前位置可以走到周围八个相邻的位置,问你走到另一个点的最短路径方案数,取模5318008。

思路:

1.两个点:(x1, y1), (x2, y2) ,dx = abs(x1 - x2), dy = abs(y1 - y2),最短路的长度一定是 max(dx, dy)。

2.通过交换坐标把两个点的相对位置变成这个样子

 3.那么现在也就是说,从下面的点开始走,如果想要走出来的是最短路径的长度,那么每一步都要固定往上走,那么现在可以dp每一步的水平方向是向左,向右,还是不变,所以用dp[ i ][ j ] 表示走到第 i 行 j 列的方案数。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int N = 5010;
const int mod = 5318008;

int n;
int dp[N][N];

int main()
{
    int t;
    int x1, y1, x2, y2;
    scanf("%d", &t);
    while(t--)
    {
        memset(dp, 0, sizeof(dp));
        scanf("%d", &n);
        scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
        int dx = abs(x1 - x2);
        int dy = abs(y1 - y2);
        if(dx > dy)
        {
            swap(x1, y1);
            swap(x2, y2);
        }
        int tot = max(dx, dy);
//        cout << x1 << " " << y1 << endl;
//        cout << x2 << " " << y2 << endl;
//        cout << tot << endl;
        dp[0][x1] = 1;
        for(int i = 1; i <= tot; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1]) % mod;
                dp[i][j] = (dp[i][j] + dp[i - 1][j + 1]) % mod;
//                cout << i << " " << j << " " << dp[i][j] << endl;
            }
        }
        printf("%d\n", dp[tot][x2]);
    }
    return 0;
}
View Code

 

 

 

posted @ 2020-05-08 13:00  LightandDust  阅读(144)  评论(0)    收藏  举报