poj 1163

来源:互联网 发布:教学实训软件 编辑:程序博客网 时间:2024/04/30 22:21
//下面是递归的思想但是2^n次超时#include <iostream>#include <cstdio>#include <algorithm>#define num 100+5using namespace std;int n;int maze[num][num];int maxsum(int x, int y){    if(x == n) return maze[x][y];//选出左值    int dx = maxsum(x + 1, y);    int dy = maxsum(x + 1, y + 1);//选出右值    return max(dx, dy) + maze[x][y];//父节点加上左右儿子 最大值为其中一个子问题的最优解}int main(){    while(scanf("%d", &n) != EOF){        for(int i = 1; i <= n; i++)            for(int j = 1; j <= i; j++)                cin >> maze[i][j];        cout << maxsum(1, 1) << endl;    }    return 0;}

//------------------------------------------------------------------------------------------------------------------------//上述递归超时的原因主要是在每一条路遍历的时候都是需要全部算出来,为了解决这个可以将每个子问题//的最优解放在数组里,碰到时调用数组,因为当n大的时候需要向下遍历计算太多次因此保存数组里只算一次解决之后的问题也叫做记忆化//时间优化#include <iostream>#include <cstdio>#define maxx 100+5using namespace std;int n;//三角形行数int maze[maxx][maxx];int vis[maxx][maxx];//记忆化递归动归数组int maxsum(int x, int y){    if(vis[x][y] != -1)return vis[x][y];    if(x == n) return maze[x][y];    int dx = maxsum(x + 1, y);    int dy = maxsum(x + 1, y + 1);    vis[x][y] = max(dx, dy) + maze[x][y];    return vis[x][y];}int main(){    while(scanf("%d", &n) != EOF){        for(int i = 1; i <= n; i++)            for(int j = 1; j <= i; j++){                scanf("%d", &maze[i][j]);                vis[i][j] = -1;//标记每个节点记录每个点最大值 为后来不重复计算准备            }        cout << maxsum(1, 1) << endl;    }    return 0;}

//------------------------------------------------------------------------------//下面对空间优化一下,之前从上向下浪费了太多空间保存了没用的,这次从下向上#include <iostream>#include <cstdio>#include <cstring>#define maxx 100+5using namespace std;int vis[maxx];//这里只需要用一位数组保存每个子问题的最优解,因为从下向上递推可以不断更新最优解int maze[maxx][maxx];int n;//行数int main(){    while(scanf("%d", &n) != EOF){        memset(vis, 0, sizeof(vis));        memset(maze, 0 , sizeof(maze));        for(int i = 1; i <= n; i++)            for(int j = 1; j <= i; j++)                scanf("%d", &maze[i][j]);        for(int j = 1; j <= n; j++)            vis[n][j] =  maze[n][j];        for(int i = n - 1; i >= 1; i--){//这里很好理解 从下向上 则这是父亲节点第一个循环控制行数            for(int j = 1; j <= i; j++){//第二个循环控制列数                vis[i][j] = max(vis[i+1][j], vis[i+1][j+1]) + maze[i][j];//maze就是父亲节点,vis是儿子节点且儿子节点持续更新dp思想            }        }        cout << vis[1][1] << endl;//因为从下向上 所以输出顶部    }    return 0;}


1 0
原创粉丝点击