P1373 小a和uim之大逃离(DP)
Posted winter-bamboo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1373 小a和uim之大逃离(DP)相关的知识,希望对你有一定的参考价值。
(点击此处查看原题)
题意
中文题,题意看题面吧。
解题思路
注意到我们只能向右和下移动,由此想到开二维的dp数组dp[i][j],代表当前所在位置
我们需要让两人取数的差值为0,由于起点和走法的不同,在同一位置上差值可能不同,为此,dp数组再多开一个维度:dp[i][j][p],表示取完位置[i,j]的数后,二者的差值为p
我最开始想到的就是三维度的dp数组,不过写完后发现方程转移就不太灵活了,主要原因在于不知道当前位置是谁进行取数,因为这将影响p的转移
为了让p可以准确的转移,我们为dp数组再多开一个维度:dp[i][j][p][type] 表示在位置[i,j]处由type取数,使得两者的差值为p(type == 0 表示小a取数,type == 1 表示uim取数)
得到了可以转移的dp数组后,此时的状态转移方程就显然易见了:
/***********************/
k = k + 1; //差距为k+1的时候会抵消,此时为了节省代码量,先处理一下
状态转移方程
dp[i][j][p][0] += dp[i-1][j][(p - val[i][j] + k)%k][1];
dp[i][j][p][0] += dp[i][j-1][(p - val[i][j] + k)%k][1];
dp[i][j][p][1] += dp[i-1][j][(p + val[i][j])%k][0];
dp[i][j][p][1] += dp[i][j-1][(p + val[i][j])%k][0];
预处理
dp[i][j][val[i][j]][0] = 1;
计算出以每个点为终点得到的最大方案数之和
sum += dp[i][j][0][1]; (1 <= i <= n , 1 <= j <= m)
代码区
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<string> #include<fstream> #include<vector> #include<stack> #include <map> #include <iomanip> #define bug cout << "**********" << endl #define show(x, y) cout<<"["<<x<<","<<y<<"] " #define LOCAL = 1; using namespace std; typedef long long ll; const int inf = 1e9 + 7; const int mod = 1e9 + 7; const int Max = 1e6 + 10; int n, m, k; int val[805][805]; int dp[805][805][20][2]; //记录从(i,j)出发,这一位置的数由(0:小a,1:uim)取走情况下,两者之差为p的方案数 /* * k = k + 1; //差距为k+1的时候会抵消,此时为了节省代码量,先处理一下 * dp[i][j][p][0] += dp[i-1][j][(p - val[i][j] + k)%k][1]; * dp[i][j][p][0] += dp[i][j-1][(p - val[i][j] + k)%k][1]; * dp[i][j][p][1] += dp[i-1][j][(p + val[i][j])%k][0]; * dp[i][j][p][1] += dp[i][j-1][(p + val[i][j])%k][0]; * * 预处理 * dp[i][j][val[i][j]][0] = 1; * * 计算出以每个点为终点得到的最大方案数之和 * sum += dp[i][j][0][1]; (1 <= i <= n , 1 <= j <= m) */ int main() #ifdef LOCAL // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); #endif scanf("%d%d%d", &n, &m, &k); k++; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%d", val[i] + j), dp[i][j][val[i][j] % k][0] = 1; int sum = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) for (int p = 0; p <= k; p++) dp[i][j][p][0] = (dp[i][j][p][0] + dp[i - 1][j][(p - val[i][j] + k) % k][1]) % mod; dp[i][j][p][0] = (dp[i][j][p][0] + dp[i][j - 1][(p - val[i][j] + k) % k][1]) % mod; dp[i][j][p][1] = (dp[i][j][p][1] + dp[i - 1][j][(p + val[i][j]) % k][0]) % mod; dp[i][j][p][1] = (dp[i][j][p][1] + dp[i][j - 1][(p + val[i][j]) % k][0]) % mod; sum = (sum + dp[i][j][0][1]) % mod; printf("%d\n", sum); return 0;
以上是关于P1373 小a和uim之大逃离(DP)的主要内容,如果未能解决你的问题,请参考以下文章