很伤心写的时候 恰好这个时候 老师问我什么是动态规划 要我说我吱吱呜呜的说了 ”一句保存前面的数组,由局部计算。。“ 本来想补充 再计算的时候很方便可以直接在 o1的时间找到 这个我都没有说脸很红 低下头
回来我想了一会大概意思就是这样我也找了一下其他大神如何留言 其实也就是 要找到状态方程式什么的 我知道 我研究很多天我一直搞不明白什么是状态方程式 也不喜欢说这么复杂 虽然现在明白了 但是想必很多小白应该也不喜欢 也搞不懂 那么今天我就说一道题目 全面剖析
这个是题目 例子也有
首先 输入2个数表示 第一个一共多少数 第二个是和
5 和15
接下来就是求和需要的数
理解题目意思那么就开始了
如果我们 只有一个数 5 我们要求和 15 可能吗 毫无疑问当然不可以 那么1 可以吗 2可以吗 好像都不行 那么我们就可以建立一张表 列出1 ,2 ,3,4,5,6.。。。15
这个是第一行的数据 0位置我没有放任何东西 一会编程需要
那么我们有2个数了 再添加一个 5 我们重新建立一个表
可以想象 第一个5 是一种情况 第二个5也是1种情况 10也有一种情况 就是5+5
那么我再举个例子 就可以开始说这个规律了
再来一个数10
我们开始思考上文有什么规律
首先是第一个5 定义为1
接下来就是第二个5 我们可以想一下 第2个5 是不应该是第一个5和第2个5 这是两种情况所以是2种情况 (这个相当于废话)
那么考虑上一个5的情况是不是 第一排的(5,5)号坐标下面有个数1 那么是否可以认为 这个一加一个1就是2了 还有一个1 哪里来 这个时候0号就可以派上用途了
看这个是不是填充了0的位置都是1 那么这个1就可以这样来了 0号位置一堆 所以说不难想象 只能在第一排的0号位置或者第2排的0号位置获得
所以我们得考虑是在哪个位置 那么我们可以看第3行10 如果有20这个数 是不是应该是上一个 0+1 刚刚满足 这个10 是第2排的(5,10) 还是第3排的(10,10)呢
毫无疑问是第二排的10
因此这个表一直下去也就完成了这个题目接下了 尝试自己画就可以解出来了
#include <iostream>
using namespace std;
int main()
{
int n, m;
cin >> n;
cin >> m;
int* arr = new int[n];
for (int i = 0; i<n; i++)
{
cin >> arr[i];
}
long long **brr = new long long*[n + 1];
for (int i = 0; i<n + 1; i++)
{
brr[i] = new long long[m + 1];
for (int j = 1; j<m + 1; j++)
{
brr[i][j] = 0;
brr[i][0] = 1;
}
}
for (int i = 1; i<n + 1; i++)
{
for (int j = 0; j<m + 1; j++)
{
if (j<arr[i - 1])
{
brr[i][j] = brr[i - 1][j];
}
else
brr[i][j] = brr[i - 1][j] + brr[i - 1][j - arr[i-1]];
}
}
cout << brr[n][m];
}