AcWing1027_方格取數
AcWing1027.方格取數
文章目錄
題目連結:AcWing1027.方格取數
1. 題目描述
設有
N
×
N
N \times N
N×N 的方格圖,我們在其中的某些方格中填入正整數,而其它的方格中則放入數字
0
0
0 。如下圖所示:
某人從圖中的左上角
A
A
A 出發,可以向下行走,也可以向右行走,直到到達右下角的
B
B
B 點。
在走過的路上,他可以取走方格中的數(取走後的方格中將變為數字
0
0
此人從 A A A 點到 B B B 點共走了兩次,試找出兩條這樣的路徑,使得取得的數字和為最大。
輸入格式
第一行為一個整數
N
N
N ,表示
N
×
N
N \times N
N×N 的方格圖。
接下來的每行有三個整數,第一個為行號數,第二個為列號數,第三個為在該行、該列上所放的數。
行和列編號從
1
1
1 開始。
一行“0 0 0”表示結束。
輸出格式
輸出一個整數,表示兩條路徑上取得的最大的和。
資料範圍
N
≤
10
N \leq 10
N≤10
輸入樣例:
8 2 3 13 2 6 6 3 5 7 4 4 14 5 2 21 5 6 4 6 3 15 7 2 14 0 0 0
輸出樣例:
67
2. 解題思路
通讀整道題,顯而易見可以設狀態為
f
(
i
1
,
j
1
,
i
2
,
j
2
)
f(i_1, j_1, i_2, j_2)
f(i1,j1,i2,j2) ,代表從
(
1
,
1
)
(1, 1)
(1,1) 出發走兩次分別走到
(
i
1
,
j
1
)
(i_1, j_1)
(i1,j1) 和
(
i
2
,
j
2
)
(i_2, j_2)
(i2,j2) 所取得路徑和。
但這種狀態表示處理“同一個格子不能被重複取值”有些複雜。
那麼同一個格子重複的條件是:
i
1
+
j
1
=
=
i
2
+
j
2
i_1 + j_1 == i_2 + j_2
據此條件,我們可以簡化狀態定義。可以定義為:
f
(
k
,
i
1
,
i
2
)
f(k, i_1, i_2)
f(k,i1,i2) ,代表所有從
(
1
,
1
)
(1, 1)
(1,1) 走到
(
i
1
,
k
−
i
1
)
(i_1, k - i_1)
(i1,k−i1) 和
(
i
2
,
k
−
i
2
)
(i_2, k - i_2)
(i2,k−i2) 的路徑的最大值。
k
k
k 表示兩條路線走到的格子的橫縱座標之和。
動態規劃分析:
狀態表示
f
(
k
,
i
1
,
i
2
)
f(k, i_1, i_2)
f(k,i1,i2) :所有從
(
1
,
1
)
(1, 1)
(1,1) 走到
(
i
1
,
k
−
i
1
)
(i_1, k - i_1)
(i1,k−i1) 和
(
i
2
,
k
−
i
2
)
(i_2, k - i_2)
(i2,k−i2) 的走法。
屬性:
m
a
x
max
max (走法的最大值)。
狀態計算:
t
=
w
(
i
1
,
j
1
)
+
{
w
(
i
2
,
j
2
)
?
}
t = w(i_1, j_1) + \{w(i_2, j_2)?\}
t=w(i1,j1)+{w(i2,j2)?} (若
i
1
=
=
i
2
i_1 == i_2
i1==i2 則不加第二部分,否則加第二部分)
- 1:向下、2:向下 : m a x { f ( k , i 1 , i 2 ) , f ( k − 1 , i 1 − 1 , i 2 − 1 ) + t } max\{f(k, i_1, i_2), f(k - 1, i_1 - 1, i_2 - 1) + t\} max{f(k,i1,i2),f(k−1,i1−1,i2−1)+t}
- 1:向下、2:向右 : m a x { f ( k , i 1 , i 2 ) , f ( k − 1 , i 1 − 1 , i 2 ) + t } max\{f(k, i_1, i_2), f(k - 1, i_1 - 1, i_2) + t\} max{f(k,i1,i2),f(k−1,i1−1,i2)+t}
- 1:向右、2:向下 : m a x { f ( k , i 1 , i 2 ) , f ( k − 1 , i 1 , i 2 − 1 ) + t } max\{f(k, i_1, i_2), f(k - 1, i_1, i_2 - 1) + t\} max{f(k,i1,i2),f(k−1,i1,i2−1)+t}
- 1:向右、2:向右 : m a x { f ( k , i 1 , i 2 ) , f ( k − 1 , i 1 , i 2 ) + t } max\{f(k, i_1, i_2), f(k - 1, i_1, i_2) + t\} max{f(k,i1,i2),f(k−1,i1,i2)+t}
3. 程式碼實現
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 15;
int n;
int w[N][N];
int f[N * 2][N][N];
int main()
{
cin >> n;
int a, b, c;
while(cin >> a >> b >> c, a || b || c) w[a][b] = c;
for (int k = 2; k <= 2 * n; k ++ )
for (int i1 = 1; i1 <= n; i1 ++ )
for (int i2 = 1; i2 <= n; i2 ++ )
{
int j1 = k - i1, j2 = k - i2;
int t = w[i1][j1];
if (i1 != i2) t += w[i2][j2];
f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1 - 1][i2 - 1] + t);
f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1][i2 - 1] + t);
f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1 - 1][i2] + t);
f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1][i2] + t);
}
printf("%d\n", f[n * 2][n][n]);
return 0;
}
4. 時間複雜度分析
三重迴圈,第一重迴圈 2 n 2n 2n 次,第二重迴圈 n n n 次,第三重迴圈 n n n 次,所以整體的時間複雜度是: O ( n 3 ) O(n^3) O(n3)
5. 說明
- 上面分析中說的同一格子重複的條件是步數相同,當步數不相同時,由於不能走回頭路,所以終點一定不同。