U1:动态规划是什么
动态规划,简称动规,是针对最优解问题的一种途径,而不是一种算法:
1.它没有一个通用的解法
2.往往是针对一种最优化问题,因而有许多不同的解题方法
动态规划使用要满足什么条件:
最优子结构和无后效性原则
最优子结构:
满足它是可以分解成几个最优子问题
无后效性:这个子问题只会受到之前的答案影响
可以分为几个阶段来完成
U2:动态规划例题 数塔问题登录 - 沐枫OJhttps://www.mfstem.org/p/524 这道题是一道经典的DP题
没有学 DP 的你,是不是会有贪心的想法呢
这明显不能用贪心
那暴力呢?
O(2^n)会超时,那就是dp了
方程:f[i][j] = a[i][j] + max(f[i+1][j], f[i+1][j+1]);
这是逆推的方法
通过后一行算出的数据,得到这一行的数据
赛马代码环节
#includeU3:背包 背包是DP的一个分支,分为01背包,完全背包,多重背包,分组背包using namespace std; #define int long long int n,a[15][15],f[15][15]; signed main(){ int n; cin >> n; for(int i = 1;i <= n;++i) for(int j = 1;j <= i;++j) { cin >> a[i][j]; f[n][j] = a[i][j];//初始化 } for(int i = n - 1;i >= 1;--i){ for(int j = 1;j <= i;++j){ f[i][j] = max(f[i + 1][j],f[i + 1][j + 1]) + a[i][j];//状态转移方程 } } cout << f[1][1] << endl; //答案 return 0; //qwq }
这次先讲前两个
T1:01背包顾名思义01背包就是没的东西可以拿一次或不拿
登录 - 沐枫OJhttps://www.mfstem.org/p/565
这是二维的状态转移方程:
f[i][j] = max(f[i - 1][j],f[i - 1][j - w[i]] + c[i]);
f[i][j] 是前i个东西在容量为j的最大值,很容易理解吧,拿和不拿
我们发现,f[i][j]只跟f[i - 1][......]有关,我们可以优化为一维数组
f[j] = max(f[j],f[j - w[i]] + c[i]);
上代码!!!
二维:
#includeusing namespace std; #define int long long int w[40],c[40],f[40][210]; signed main(){ int m,n; scanf("%lld%lld",&m,&n); for(int i = 1;i <= n;++i)scanf("%lld%lld",&w[i],&c[i]); for(int i = 1;i <= n;++i){ for(int j = 0;j <= m;++j){ if(j < w[i])f[i][j] = f[i - 1][j]; else f[i][j] = max(f[i - 1][j],f[i - 1][j - w[i]] + c[i]); } } printf("%lldn",f[n][m]); return 0; }
一维:
#includeT2:完全背包using namespace std; #define int long long int w[40],c[40],f[210]; signed main(){ int m,n; scanf("%lld%lld",&m,&n); for(int i = 1;i <= n;++i)scanf("%lld%lld",&w[i],&c[i]); for(int i = 1;i <= n;++i){ for(int j = m;j >= w[i];--j){ f[j] = max(f[j],f[j - w[i]] + c[i]); } } printf("%lldn",f[m]); return 0; }
登录 - 沐枫OJhttps://www.mfstem.org/p/566 完全背包,就是每种物品可以取无数个,问你最大值
方程:
f[i][v] = max(f[i - 1][v],f[i-1][v-k*w[i]]+k*c[i]);
可以改成
f[i][v] = max([i-1][v], f[i][v-w[i]] + c[i]);
#includeendusing namespace std; int w[37],v[37],f[1005]; int main(void){ int n,m; cin >> m >> n; for(int i = 1;i <= n;++i)cin >> w[i] >> v[i]; for(int i = 1;i <= n;++i){ for(int j = w[i];j <= m;++j){ f[j] = max(f[j],f[j - w[i]] + v[i]); } } cout << "max=" << f[m] << endl; return 0; }



