题目描述:
hybest担任着拯救文太的任务。
有一天在施展膜法的时候,不小心转移到一个被施下诅咒的矩阵之中。他在矩阵中可以向着相邻的格子移动(斜向的移动是不允许的)。
矩阵每个位置都有很多可以采摘的查克拉之果,hybest要走出这个矩阵,他每经过一个位置,这个位置的查克拉之果都会被他吸收。
但是由于矩阵里存在强大的诅咒,hybest在走出矩阵时,获得的查克拉之果数量会被做一个取模运算,模 k 。
hybest想通过膜法探知这个矩阵的真相,于是他在法阵之中召唤出了上古神谕,神谕上写道:
矩阵中每个位置的查克拉果数量,等于从矩阵第一行第一列的位置走到这个位置的最近路线的方案数乘以 y 。
已知,hybest进入矩阵时,出现在矩阵第n行,第m列的位置,出口在矩阵的第x行,第x列。请你帮助hybest,拿到最多的查克拉之果。
请注意,为了尽快拯救文太,hybest只选择跑的最快的路线(即所移动的步数最少)。
输入格式:
输入一行,五个整数,n,m,x,k,y(0< n,m <= x, 0< x,k <= 1000, 0 < y <= 10)
输出格式:
输出一个整数单独一行,代表在跑的最快的前提下,hybest可以为文太带来多少查克拉之果。
样例输入:
1 1 5 79 1
样例输出:
69
#include<stdio.h>
#include<iostream>
#include<bitset>
using namespace std;
bitset<1005> dp[2][1005];
int map[1005][1005];
int main()
{
int n, m, x, k, y;
scanf("%d%d%d%d%d", &n, &m, &x, &k, &y);
map[1][1] = y%k;
for (int i = 1; i <= x; i++)
for (int j = 1; j <= x; j++)
if(i!=1||j!=1)map[i][j] = (map[i - 1][j] + map[i][j - 1])%k;
dp[(n-1) % 2][m][0] = 1;
for (int i = n; i <= x; i++)
for (int j = m; j <= x; j++)
{
dp[i % 2][j] = (dp[!(i % 2)][j] | dp[i%2][j-1]);
dp[i % 2][j] = ((dp[i % 2][j] << map[i][j]) | (dp[i % 2][j] >> (k - map[i][j])));
//cout << i << ' ' << j << ' ' << dp[i % 2][j] << endl;
}
for (int i = k-1; i >= 0; i--)
{
if (dp[x % 2][x][i] == 1)
{
printf("%d\n", i);
break;
}
}
}