动态规划算法设计——实例1
最近复习了算法的前两章,第一章主要是基础知识,函数的界以及地推方程求解的几种方法。第二章讲了分治策略。看了很多,但感觉没有吸收到很多东西。想到假期后马上就要交动态规划算法作业了。干脆直接做题。
题目描述
- 求 m a x g 1 ( x 1 ) + g 2 ( x 2 ) + g 3 ( x 3 ) max\ g_1(x_1)+g_2(x_2)+g_3(x_3) max g1(x1)+g2(x2)+g3(x3)
- 限制条件: x 1 2 + x 2 2 + x 3 2 ≤ 10 x_1^2+x_2^2+x_3^2\leq10 x12+x22+x32≤10
- 其中
g
1
g
2
g
3
g_1\ g_2 \ g_3
g1 g2 g3是三个不同的收益函数。
题目思路
- 首先来一波吐槽,这每个x一共才4种取值,直接暴力把每种情况的值算出来,取个最大的不香嘛?2333
- 这道题要求我们用动态规划的算法来求解。按照我们之前积累的经验,我们需要在求解时需要用到规模更小的子问题,所以用什么参数来划分问题就很重要。我一开始的想法是把x1的值作为一个规模参数,x2的值作为一个参数,然后是x3。后来发现这完全不对,把这三个都列出来不就是暴力求解嘛2333。这时我一点思路都没有,便去看了一眼答案。
- 答案的优化函数 F k ( y ) F_k(y) Fk(y),k表示选择前k个x,y表示平方和的限制,在这种情况下的最大收益。后来一想,这不是和背包问题的思路一模一样嘛?背包问题的k表示选择前k个物品,然后y表示背包的限重。这里只不过背包限重变成了平方和的限制。
- 明白了这一点,我们很容易写出递归方程(好吧,也不是很容易
- F k ( y ) = max 0 ≤ x k ≤ ⌊ y ⌋ F k − 1 ( y − x k 2 ) + g k ( x k ) F_k(y)=\max \limits_{0\leq x_k \leq \lfloor \sqrt y \rfloor} F_{k-1}(y-x_k^2)+g_k(x_k) Fk(y)=0≤xk≤⌊y⌋maxFk−1(y−xk2)+gk(xk)
- 当我们选择了前k个x时,我们就需要遍历 x k x_k xk的取值,然后把平方和限制剩余的部分 y − x k 2 y-x_k^2 y−xk2在前k-1个x中进行取最大收益,最后加上 x k x_k xk带来的收益 g k ( x k ) g_k(x_k) gk(xk)。就是 F k ( y ) F_k(y) Fk(y)。也就是选择前k个x,在平方和限制为y的情况下的最大收益。
代码实现
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int g[4][4] = {0, 0, 0, 0, 2, 4, 7, 11, 5, 10, 16, 20, 8, 12, 17, 22}; //第一个下标来区分不同的投资函数,分别有g1,g2和g3,g0闲置。第二个下标用来表示投资的个数,数目从0~3。
int F[4][11] = {0}; //优化函数F[k][y],下标k表示选择前k个个x(其实一共也才3个x2333),k表示x_1^2+...+x_k^2 <= y
int Re[4][11] = {-1}; //备忘录函数,表示在选择前k个x,平方和的限制为y的情况下,选择x_k的个数(可以形象的理解为理解为选择了几个x_k)。
for (int k = 1; k <= 3; k++) //遍历k,表示选择前几个x
{
for (int y = 0; y <= 10; y++) //遍历y,表示平方和的范围
{
int max = 0;
for (int x = 0; x <= sqrt(y); x++) //遍历选择的第k个x的取值范围,从0~3
{
if ((F[k - 1][y - x * x] + g[k][x]) > max)
{
max = F[k - 1][y - x * x] + g[k][x];
Re[k][y] = x;
}
}
F[k][y] = max; //得到在选择前k个x,平方和限制为y下的最大收益
}
}
cout << F[3][10] << endl;
int i = 3;
int y = 10;
while (i)
{
cout << "x_" << i << "的值:" << Re[i][y] << endl;
y -= Re[i][y] * Re[i][y];
i--;
}
return 0;
}
//运行结果
➜ algorithm git:(main) ✗ g++ question1.cpp -o question1.exe && ./question1.exe
37
x_3的值:2
x_2的值:2
x_1的值:1