问题
捡两次废纸
当前有M * N格子构成的城市。这城市各处都有垃圾。
范贤捡废纸是从最左上角的格子(1, 1)出发移动到最右下角的 (M, N) ,这时需要走最短的路径。即,只能移动到相邻的向右或向下的格子。
在这里要进一步重新从 (M, N)移动到 (1, 1)再次捡废纸。这时也要走最短的路径。即,只能移动到相邻的向左或向上的格子。
需要注意的是捡完一次废纸就再没有废纸了。
这时,请输出范贤能收集到的废纸量的最大值。
输入
第一行给出测试用例个数T(1 ≤ T ≤ 20)。
每个测试用例的第一行给出N, M(2 ≤ N, M ≤ 100)。下一个M行,每行给出N个字符。
'*'是表示可以行走的有废纸的地方。
'.'是表示可以行走,但没有废纸的地方。
'#'是表示不能行走的地方。
当前已确定(1, 1)和 (M, N)是可以去的地方。
还有确定两点之间有路径。
输出
每个测试用例,通过一行输出范贤可以捡到的最多废纸量。
案例输入
2
9 7
*........
.....**#.
..**...#*
..####*#.
.*.#*.*#.
...#**...
*........
5 5
.*.*.
*###.
*.*.*
.###*
.*.*.
案例输出
7
8
案例补充
在第一个测试用例中, 范贤到达 (M, N)位置时,城市变成如下:
xxxxx....
....xxx#.
..**..x#*
..####x#.
.*.#*.x#.
...#**xxx
*.......x
X表示范贤的移动路径。现在为止收集的废纸是5个。重新移动到 (1, 1)时,城市变成如下:
yxxxx....
y...xxx#.
yyyyyyy#*
..####y#.
.*.#*.y#.
...#**yxx
*.....yyy
Y表示范贤的移动路径。范贤收集的总废纸量为7个,所以输出7。
第二个测试用例的解,如下所示:
yxxxx
y###x
y.*.x
y###x
yyyyy
#include <stdio.h>
#include <string.h>
#include <algorithm>
int Dp[210][110][110], W, H;
char ch[110];
bool inp[110][110];
bool itr[110][110];
int main()
{
int T; scanf("%d", &T);
while (T--){
memset(Dp, 0, sizeof Dp);
memset(inp, 0, sizeof inp);
memset(itr, 0, sizeof itr);
int i, j, k;
scanf("%d%d\n", &W, &H);
for (i = 1; i <= H; i++){
scanf("%s", ch);
for (j = 1; j <= W; j++){
if (ch[j - 1] != '#')inp[i][j] = true;
if (ch[j - 1] == '*')itr[i][j] = true;
}
}
for (i = 2; i <= W + H; i++){
for (j = 1; j<i; j++){
if (j>H || i - j>W || !inp[j][i - j])continue;
for (k = j; k<i; k++){
if (k>H || i - k>W || !inp[k][i - k])continue;
int t = 0;
t = std::max(std::max(Dp[i - 1][j - 1][k], Dp[i - 1][j][k]), std::max(Dp[i - 1][j - 1][k - 1], Dp[i - 1][j][k - 1]));
Dp[i][j][k] = (j == k ? itr[j][i - j] : itr[j][i - j] + itr[k][i - k]) + t;
}
}
}
printf("%d\n", Dp[W + H][H][H]);
}
return 0;
}