解題報告:
思路:我採用的是從下往上遞推,那麼dp[0][0]就是答案,遞推式爲:dp[i][j] = max(dp[i+1][j], dp[i+1][j+1]) + num[i][j]。顯然最後一行要單獨處理。對於路徑:可以定義一個三維數組path,用來記錄當前點從哪個點轉移過來的,第三維爲0記錄的是x座標,爲1記錄y座標。
代碼:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 100 + 10;
ll num[N][N];
ll dp[N][N], path[N][N][2];
ll n;
void solve(){
memset(dp, 0, sizeof(dp));
for(ll i=0; i<n; ++i){
dp[n-1][i] = num[n-1][i];
path[n-1][i][0] = -1;
path[n-1][i][1] = -1;
}
for(ll i=n-2; i>=0; --i){
for(ll j=0; j<=i; ++j){
if(dp[i+1][j] > dp[i+1][j+1]){
dp[i][j] = dp[i+1][j] + num[i][j];
path[i][j][0] = i+1;
path[i][j][1] = j;
}else {
dp[i][j] = dp[i+1][j+1] + num[i][j];
path[i][j][0] = i+1;
path[i][j][1] = j+1;
}
}
}
printf("%lld\n", dp[0][0]);
printf("%lld", num[0][0]);
ll x = 0, y = 0;
while(true){
ll xx = x, yy = y;//下面賦值會改變x
x = path[xx][yy][0];
y = path[xx][yy][1];
if(x == -1 || y == -1)break;
printf(" %lld", num[x][y]);
}
puts("");
}
int main(){
while(~scanf("%lld", &n)){
for(ll i=0; i<n; ++i){
for(ll j=0; j<=i; ++j){
scanf("%lld", &num[i][j]);
}
}
solve();
}
return 0;
}