一篇题解
szh_AK_all · · 题解
分析
看到这题,很容易想到 dp。
在不考虑牛每走三步便要吃一次草的情况下,对于每个点
接着考虑牛每走三步便要吃一次草的条件。
由于有步数限制,所以在
很显然的一个转移是由
但是单纯的这样转移是错误的,因为这些步数对
用上述反例思考另一个转移,我们可以用当前步数
int now = min(a[i - 1][j], a[i + 1][j]);
now = min(now, min(a[i][j + 1], a[i][j - 1]));
int tmp = 0;
if (k + 1 == 3)
tmp = now;
else if (k + 2 == 3)
tmp = a[i][j];
else if (k + 3 == 3)
tmp = a[i + 1][j];
f[i + 1][j][k] = min(f[i + 1][j][k], f[i][j][k] + 3 * T + tmp);
在考虑是否可以转移到
最后,考虑到这个转移是有后效性的,也就是说对于一个位置,在被之前的某个状态转移过来时,它对于其它的位置而言,此时可能是最优的。那么可以进行多次转移,对于最优秀的位置,它被“扩散”到、成为优秀的位置时,最多要进行
当然,一个在考场上骗分的做法是直接转移 教育诱导意义。
Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[105][105];
int f[105][105][5];
signed main() {
int n, T;
cin >> n >> T;
for (int i = 0; i <= 103; i++)
for (int j = 0; j <= 103; j++)
a[i][j] = f[i][j][0] = f[i][j][1] = f[i][j][2] = 100000000000000000;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> a[i][j];
f[1][1][0] = 0;
for (int ii = 1; ii <= 2 * n; ii++)
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
for (int k = 0; k < 3; k++) {
f[i + 1][j][(k + 1) % 3] = min(f[i + 1][j][(k + 1) % 3], f[i][j][k] + T + (k + 1 == 3) * a[i + 1][j]);
f[i][j + 1][(k + 1) % 3] = min(f[i][j + 1][(k + 1) % 3], f[i][j][k] + T + (k + 1 == 3) * a[i][j + 1]);
f[i - 1][j][(k + 1) % 3] = min(f[i - 1][j][(k + 1) % 3], f[i][j][k] + T + (k + 1 == 3) * a[i - 1][j]);
f[i][j - 1][(k + 1) % 3] = min(f[i][j - 1][(k + 1) % 3], f[i][j][k] + T + (k + 1 == 3) * a[i][j - 1]);
int now = min(a[i - 1][j], a[i + 1][j]);
now = min(now, min(a[i][j + 1], a[i][j - 1]));
int tmp = 0;
if (k + 1 == 3)
tmp = now;
else if (k + 2 == 3)
tmp = a[i][j];
else if (k + 3 == 3)
tmp = a[i + 1][j];
f[i + 1][j][k] = min(f[i + 1][j][k], f[i][j][k] + 3 * T + tmp);
tmp = 0;
if (k + 1 == 3)
tmp = now;
else if (k + 2 == 3)
tmp = a[i][j];
else if (k + 3 == 3)
tmp = a[i][j + 1];
f[i][j + 1][k] = min(f[i][j + 1][k], f[i][j][k] + 3 * T + tmp);
tmp = 0;
if (k + 1 == 3)
tmp = now;
else if (k + 2 == 3)
tmp = a[i][j];
else if (k + 3 == 3)
tmp = a[i][j - 1];
f[i][j - 1][k] = min(f[i][j - 1][k], f[i][j][k] + 3 * T + tmp);
tmp = 0;
if (k + 1 == 3)
tmp = now;
else if (k + 2 == 3)
tmp = a[i][j];
else if (k + 3 == 3)
tmp = a[i - 1][j];
f[i - 1][j][k] = min(f[i - 1][j][k], f[i][j][k] + 3 * T + tmp);
}
}
}
cout << min(f[n][n][0], min(f[n][n][1], f[n][n][2]));
}