洛谷1373 小a和uim之大逃离
原题链接
只要想好状态,这题就是水题了,转移方程完全没难度。。
设\(f[i][j][w][u]\)表示走到\((i, j)\)格,小\(a\)和\(uim\)所取得魔力值的差值为\(w\),该格由(\(u = 0\)则小\(a\)取,\(u = 1\)则\(uim\)取)时的总方案数。
设格子\((i, j)\)的魔力值为\(a[i][j]\),则有状态转移方程:
\(\qquad\qquad f[i][j][w][0] = f[i][j][w][0] + f[i - 1][j][v][1] + f[i][j - 1][v][1],\quad v = (w - a[i][j] + k + 1) \% (k + 1)\)
\(\qquad\qquad f[i][j][w][1] = f[i][j][w][1] + f[i - 1][j][v][0] + f[i][j - 1][v][0],\quad v = (w + a[i][j]) \% (k + 1)\)
因为小\(a\)能从任意一个格子开始走,所以初值为\(i = 1 \to n, j = 1 \to m, f[i][j][a[i][j]][0] = 1\)。
最后答案为\(\sum\limits_{i = 1}^n\sum\limits_{j = 1}^m f[i][j][0][1]\)
#include<cstdio>
using namespace std;
const int N = 810;
const int M = 16;
const int mod = 1e9 + 7;
int f[N][N][M][2], a[N][N];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline long long MOD(long long x)
{
if (x < mod)
return x;
return x - mod;
}
int main()
{
int i, j, n, m, k, o, w, v, s = 0;
n = re();
m = re();
k = re();
o = k + 1;
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
{
a[i][j] = re();
f[i][j][a[i][j]][0] = 1;
}
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
for (w = 0; w <= k; w++)
{
v = (w - a[i][j] + o) % o;
f[i][j][w][0] = MOD(MOD(1LL * f[i - 1][j][v][1] + f[i][j - 1][v][1]) + f[i][j][w][0]);
v = (w + a[i][j]) % o;
f[i][j][w][1] = MOD(MOD(1LL * f[i - 1][j][v][0] + f[i][j - 1][v][0]) + f[i][j][w][1]);
if (!w)
s = MOD(1LL * s + f[i][j][0][1]);
}
printf("%d", s);
return 0;
}
posted on 2018-10-22 14:36 Iowa_Battleship 阅读(95) 评论(0) 编辑 收藏 举报