动态规划初次学习
子问题
为了解决自身所面临的问题,交给下一层几个问题(通过这几个问题解决自己的问题),这几个问题就是子问题
(金矿问题 理解思想)
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];
}