单测试点时限: 2.0 秒
内存限制: 256 MB
有形如下图所示的数塔,从顶部出发,在每一结点可以选择向左走或是向右走,一起走到底层,要求找出一条路径,使路径上的数字和最小。
9
12 15
10 6 8
2 18 9 5
19 7 10 4 16
输入
输入数据首先包括一个整数 C,表示测试实例的个数,每个测试实例的第一行是一个整数 N(1 <= N <= 100),表示数塔的高度,接下来用 N 行数字表示数塔,其中第 i 行有个 i 个整数,且所有的整数均在区间 [0,99] 内。
输出
对于每个测试实例,输出路径上的数字和最小值。
样例
input
1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
这个题目的数据只是为了方便大家看,读入的时候不需考虑多余的空格和换行
output
17
题目大意:
从数塔上层走到最底层,每次可以选择向左或向右,求路径之和最小值。
题目解析:
数塔,标准的动态规划题,用dp[i][j]表示从顶层到i,j这个位置路径之和的最小值,则初始化dp[1][1]=A[1][1],每次向下判断。状态转移方程:
dp[i+1][j]=min(dp[i][j]+A[i+1][j],dp[i+1][j]);
dp[i+1][j+1]=min(dp[i][j]+A[i+1][j+1],dp[i+1][j+1]);
具体代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 105
int A[MAXN][MAXN];
int dp[MAXN][MAXN];
int main() {
int T,m,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
fill(dp[0],dp[0]+MAXN*MAXN,999999999);
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&A[i][j]);
dp[1][1]=A[1][1];
for(int i=1;i<n;i++){
for(int j=1;j<=i;j++){
dp[i+1][j]=min(dp[i][j]+A[i+1][j],dp[i+1][j]);
dp[i+1][j+1]=min(dp[i][j]+A[i+1][j+1],dp[i+1][j+1]);
}
}
int minres=999999999;
for(int i=1;i<=n;i++){
if(dp[n][i]<minres)
minres=dp[n][i];
}
cout<<minres<<endl;
}
return 0;
}