撿兩次廢紙(DP)



問題

 

撿兩次廢紙

 

當前有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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章