poj1163 dp入门题 数塔

来源:互联网 发布:淘宝收货姓名写什么好 编辑:程序博客网 时间:2024/04/29 02:21

数塔问题:给你一个数字三角形, 形式如下:
5 //三角形行数。下面是三角形
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
找出从第一层到最后一层的一条路,使得所经过的权值之和者最大。
路径上的每一步都只能往左下或右下走。三角形的行数大于1小于等于100。
问题解决思路:用递推型的dp解题,有自底向上的”人人为我“与 自顶向下的“我为人人”。
自底向上的思路是从底部向上逐级递推求出最终结果
状态dp[i][j]表示i行j列到底层所经过的权值之和的最大值
状态转移方程为:dp[i][j]=max(dp[i+1][j],dp[i+1][j])+a[i][j];
最终输出结果即为dp[0][0]
源代码:

#include<iostream>using namespace std;int a[105][105];int dp[105][105];int main(){    int n;    while(cin>>n){        for(int i=0;i<n;i++)            for(int j=0;j<=i;j++)                cin>>a[i][j];        for(int i=n-1;i>=0;i--)            for(int j=0;j<=i;j++)                if(i==n-1)                    dp[i][j]=a[i][j];                else                    dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+a[i][j];        cout<<dp[0][0]<<endl;    }    return 0;}

由于dp[i][j]只与dp[i+1][j]及dp[i+1][j+1]有关,在每次状态转移之后第i+1行的数据就不再需要,所以可以只用一个一维数组dp[j]表示当前行各列到底层的权值和最大的路径的权值和。进而发现可以不用再开数组,直接用二维数组a即可满足状态转移过程中对内存的需求.
状态转移方程:a[i][j]=max(a[i+1][j],a[i+1][j+1])+a[i][j];
输出a[0][0];
源代码:

#include<iostream>using namespace std;int a[105][105];int main(){    int n;    while(cin>>n){        for(int i=0;i<n;i++)            for(int j=0;j<=i;j++)                cin>>a[i][j];        for(int i=n-2;i>=0;i--)            for(int j=0;j<=i;j++)                a[i][j]=max(a[i+1][j],a[i+1][j+1])+a[i][j];        cout<<a[0][0]<<endl;    }    return 0;}

自顶到下的思路是从顶端向下逐步更新状态来求得最优解。
状态dp[i][j]表示从i行j列到底层的最优解;
状态转移方程:dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j];
最后的结果为底层数字的最大值。
优化好空间后的源代码:

#include<iostream>#include<algorithm>using namespace std;int a[105][105];int main(){    int n;    while(cin>>n){        for(int i=1;i<=n;i++)            for(int j=1;j<=i;j++)                cin>>a[i][j];        for(int i=2;i<=n;i++)            for(int j=0;j<i;j++)                a[i][j]=max(a[i-1][j],a[i-1][j-1])+a[i][j];        cout<<*max_element(a[n],a[n]+n+1)<<endl;//求数组中的最大值    }    return 0;}
0 0
原创粉丝点击