問題
撿兩次廢紙
當前有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;
}