动态规划初学

动态规划初次学习

子问题
为了解决自身所面临的问题,交给下一层几个问题(通过这几个问题解决自己的问题),这几个问题就是子问题

(金矿问题 理解思想)
1.最优子结构
通过得到的最优子问题,加上母问题进行的优化选择所得到的情况为最优子结构
得到左右部下的答案(必须 最优,金子数量最多),加上原先的答案,就可以完成
2.子问题重叠
子问题和母问题所遇到的是相同的问题,解决办法是基本完全相同,就是传递参数是不同的。
国王,左右部下,得到金矿数,人数,求最多能开采的金字数。
3.边界
要找到停止的条件!不然死了。(动态规划通常基于一个递推公式及一个或多个初始状态,,递归, 结束条件)

4.子问题独立
母问题在对子问题进行选择时,被选择的子问题不相互影响。
不关心其他人如何计算怎样开采金矿。

核心:状态和状态转移方程(描述具体的算法)

数字三角形
从第一行数开始,每次往左下,或右下走一格,直到最后一行,把沿途经过的数全部加起来,使和最大?

//1.txt
1
3 2
4 11 11

结果15

解法1

1.cpp
#include<iostream>
#include<fstream>
using namespace std;
int a[5][5] = {0};
int Maxsum(int r, int j)
{
    if(r == 2)
    return a[r][j];
    int max1 = Maxsum(r+1, j);
    int max2 = Maxsum(r+1, j+1);
    if(max1 > max2)
    return a[r][j] + max1;
    else 
    return a[r][j] + max2; 
}

int main(void)
{
    ifstream file; 
    int max;
    file.open("1.txt");
    for(int i = 0 ;i < 3; i++)
    {

        for(int j = 0; j <= i; j++)
        {
            file >> a[i][j];
        }   
    }
    for(int i = 0 ;i < 3; i++)
    {

        for(int j = 0; j <=i; j++)
        {
            cout << a[i][j] << "     ";
        }
        cout << endl; 

    }
    max = Maxsum(0, 0);
    cout << max;
}

解法1是很简单的递归,然而这种程序在执行更大的三角形时,会浪费很多时间,重复会很多。
1,1
2,1 |2,2
3,1|3,2|3,2|3,3

解法2
优化问题,将没计算的计算出来并保存,计算出来的直接使用,快了~

#include<iostream>
#include<fstream>

using namespace std;

int a[5][5] = {0};
int aMaxsum[5][5] = {-1};
int Maxsum(int r, int j)
{
    if(r == 2)
    return a[r][j];
    if(aMaxsum[r+1][j] == -1)
    //Maxsum(r+1, j+); 没有计算过de
    aMaxsum[r+1][j] = Maxsum(r+1, j);

    if(aMaxsum[r+1][j+1] == -1)
    //Maxsum(r+1, j+1) 没有计算过de  
    aMaxsum[r+1][j+1] = Maxsum(r+1, j+1);
    if(aMaxsum[r+1][j] > aMaxsum[r+1][j+1])
    return aMaxsum[r+1][j] + a[r][j];
    return aMaxsum[r+1][j+1] + a[r][j];
}

int main(void)
{
    ifstream file; 
    int max;
    file.open("1.txt");
    for(int i = 0 ;i < 3; i++)
    {

        for(int j = 0; j <= i; j++)
        {
            file >> a[i][j];
        }       
    }   
    for(int i = 0 ;i < 3; i++)
    {

        for(int j = 0; j <=i; j++)
        {
            cout << a[i][j] << "     ";
        }
        cout << endl;       
    }
    for(int i = 0 ;i < 5; i++)
    {

        for(int j = 0; j < 5; j++)
        {
             aMaxsum[i][j] = -1;
        }
        cout << endl;   
    }   
    max = Maxsum(0, 0);
    for(int i = 0 ;i < 5; i++)
    {

        for(int j = 0; j < 5; j++)
        {
            cout << aMaxsum[i][j] << "    ";
        }
        cout << endl;   
    }
    cout << endl;
    cout << "最大和是:  " << max;
}

解法3
不用递归 ,在矩阵中玩~~

#include<iostream>
#include<fstream>

using namespace std;
int a[5][5] = {0};
int b[5][5] = {0};

int main(void)
{
    ifstream file; 
    int max;
    file.open("1.txt");
    for(int i = 0 ;i < 3; i++)
    {

        for(int j = 0; j <= i; j++)
        {
            file >> a[i][j];
        }       
    }

    for(int i = 0 ;i < 3; i++)
    {

        for(int j = 0; j <=i; j++)
        {
            cout << a[i][j] << "     ";
        }
        cout << endl;       
    }
    for(int i = 0 ;i < 5; i++)
    {

        for(int j = 0; j < 5; j++)
        {
             b[i][j] = 0;
        }       
    }
    for(int i = 0; i < 3; i++)
    b[2][i] = a[2][i];

    for(int i = 2; i >= 0;i--)
    {
        for(int j = 0; j < i; j++)
        {
            if((b[i][j] + a[i-1][j]) < (b[i][j+1] + a[i-1][j])) 
            {
                b[i-1][j] = (b[i][j+1] + a[i-1][j]);

            }   
            else
            {
                b[i-1][j] = (b[i][j] + a[i-1][j]);
            }   
        }
    }
    cout << endl; 
    for(int i = 0 ;i < 3; i++)
    {   
        for(int j = 0; j <=i; j++)
        {
            cout << b[i][j] << "     ";
        }
        cout << endl;   
    }
    cout << "max = " << b[0][0];

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值