2月10号自习总结

今天有点颓废,控制不住想刷短视频(短视频害人啊!)就学了一点东西,刷了一个题(@_@)

 今天总结了一下动态规划:

概念:

动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。

所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的

 解题步骤:

现在为止任然对动态规划是一种懵逼的状态,一些简单的题对着状态转移公式写题目还没完全理解就AC了,一遇到难一点的题目就完全一点思路没有,然后看题解,然后继续照葫芦画瓢陷入这种恶性循环中。

看了一个教程上的动态规划解题步骤:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

 对于动态规划问题,拆解为如上五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!

 动态规划的两个主要问题:

背包问题:

子序列问题:

 这些问题还等待着慢慢去学习

刷题:

一个简单的01背包:

传送门

题目描述

有一个箱子容量为 VV,同时有 nn 个物品,每个物品有一个体积。

现在从 nn 个物品中,任取若干个装入箱内(也可以不取),使箱子的剩余空间最小。输出这个最小值。

输入格式

第一行共一个整数 VV,表示箱子容量。

第二行共一个整数 nn,表示物品总数。

接下来 nn 行,每行有一个正整数,表示第 ii 个物品的体积。

输出格式

  • 共一行一个整数,表示箱子最小剩余空间。

输入输出样例

输入 #1

24
6
8
3
12
7
9
7

输出 #1

0

说明/提示

对于 100%100% 数据,满足 0<n≤300<n≤30,1≤V≤200001≤V≤20000。

【题目来源】

NOIP 2001 普及组第四题

 思路就不用说了,直接看代码:

//dp一维
/*
#include<bits/stdc++.h>
using namespace std;
int main(){
	int v,n;
	scanf("%d %d",&v,&n);
	int jk[40]={0};
	int dp[20012]={0};//箱子容量为i时装入物体最多的数量
	for(int i=1;i<=n;i++){
		scanf("%d",&jk[i]);
	}
	for(int i=1;i<=n;i++){//决策第n个物体
		for(int k=v;k>=jk[i];k--){//箱子容量为k时
			dp[k]=max(dp[k],dp[k-jk[i]]+jk[i]);//dp[k-jk[i]]:箱子在装了物体i之后剩余箱子容量能装的最大重量
		}
	}
	printf("%d",v-dp[v]);
}
*/
//dp二维


#include<bits/stdc++.h>
using namespace std;
int dp[20012][20012] = {0}; //箱子容量为i时装入物体最多的数量
int main() {
	int v, n;
	scanf("%d %d", &v, &n);
	int jk[40] = {0};
	for (int i = 1; i <= n; i++) {
		scanf("%d", &jk[i]);
	}
	for (int i = 1; i <= n; i++) { //决策第n个物体
		for (int k = 1; k <= v; k++) { //箱子容量为k时
			if (k < jk[i]) {
				dp[i][k] = dp[i - 1][k]; //状态继承
			} else {
				dp[i][k]=max(dp[i-1][k],dp[i-1][k-jk[i]]+jk[i]);
			}
		}
	}
	printf("%d", v - dp[n][v]);
}






/*
//dfs深搜
#include<stdio.h>
int jk[40], book[40] = {0};
int v, n, max = 0, tt = 0;
void dfs() {
	for (int i = 0; i < n; i++) {
		if (book[i] == 0 && tt + jk[i] <= v) {
			book[i] = 1;
			tt += jk[i];
			if (tt > max) {
				max = tt;
			}
			dfs();
			book[i] = 0;
			tt -= jk[i];
		}
	}
}
int main() {
	scanf("%d %d", &v, &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &jk[i]);
	}
	dfs();
	printf("%d", v - max);
}
*/

 但愿这个世界没有手机

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值