动态规划试题
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
int dp[maxn][maxn];
int main(){
cin >> n;
int a[n][n];
fill(dp[0],dp[0]+MAXV*MAXV,0);
for(int i=0 ; i < n; i++){
for(int j=0; j <= i; j++){
cin >> a[i][j];
}
}
for(int i=0; i < n; i++){
dp[n-1][i] = a[n-1][i];
}
for(int i=n-1; i >=0; i--){
for(int j=0; j <= i; j++){
dp[i][j] = max(dp[i+1][j],dp[i+1][j+1]) + a[i][j];
}
}
cout << dp[0][0] << endl;
return 0;
}
②
//最大连续子序列和
}
for(int i=1; i <= m; i++){
for(int j=n; j >= k[i]; j--){
f[j] = max(f[j],f[j-k[i]]+k[i]*v[i]);
}
}
cout << f[n];
return 0;
}
多重背包
有N种物品和一个容量是V的背包。
第ii种物品最多有sisi件,每件体积是vivi,价值是wiwi。
完全背包
[无限量]的采摘药输入:
70 3
71 100
69 1
1 2
输出:140
每个数组在满足条件,可以遍历多次
#include<iostream>
#include<algorithm>
using namespace std;
int f[100001];
int a[10001],b[10001];
int main(){
输入样例:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例:
30
#include<iostream>
#include<algorithm>
const int MAXV = 10010;
using namespace std;
int dp[MAXV][MAXV];
int main(){
int n;
if(A[i] > A[j] && (dp[j] + 1) > dp[i]){
dp[i] = dp[j] + 1;
}
}
ans = max(ans,dp[i]);
}
cout << ans << endl;
return 0;
}
④
//最长公共子序列
给定两个长度分别为N和M的字符串A和B,求既是A的子序列又是B的子序列的字符串长度最长是多少。
using namespace std;
int f[20005],w[35];
int main()
{
int v,n;
cin>>v>>n;
for(int i=1;i<=n;i++)cin>>w[i];
for(int i=1;i<=n;i++){
for(int j=v;j>=w[i];j--){
f[j]=max(f[j],f[j-w[i]]+w[i]);
300 5
400 3
200 2
输出:
3900
#include<bits/stdc++.h>
using namespace std;
int f[30010],k[30],v[30];
int n,m;
int main(){
cin >> n >> m;
for(int i=1; i<= m; i++){
cin >> k[i] >> v[i];
//最长不下降子序列
给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。
数据范围
1≤N≤1000,
−10^9≤数列中的数≤10^9
输入样例:
7
3 1 2 1 8 5 6
输出样例:
4
#include<iostream>
const int MAXV = 10010;
using namespace std;
int n,m;
cin >> n >> m;
for(int i=1; i <= m; i++){
cin >> a[i] >> b[i];
}
for(int i=1; i<=m; i++){
for(int j=a[i]; j <=n; j++){
f[j] = max(f[j],f[j-a[i]]+b[i]);
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXV = 10010;
int A[MAXV],dp[MAXV];
int main(){
int n;
cin >> n;
for(int i=0; i < n; i++){
数据范围
1≤N≤1000,
输入样例:
4 5
acbd
abedc
输出样例:
3
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1010;
char A[maxn],B[maxn];
}
}
cout << f[n];
return 0;
}
01背包
实现代码:采药-传送门
输入:
70 3
71 100
69 1
1 2
输出:3
每个数组遍历一遍
#include<iostream>
#include<algorithm>
using namespace std;
int a[101],b[101];
int f[10001];
设第jj件物品的价格为v_[j],重要度为w_[j],共选中了k件物品,编号依次为j_1,j_2,…,j_k,则所求的总和为:
w_[j_k]v[ j1 ]×w[ j1 ]+v[ j2 ]×w[ j2 ]+…+v[ jk ]×w[ jk ]。
请你帮助金明设计一个满足要求的购物单。
输入格式
第一行,为2个正整数,用一个空格隔开:n m(其中N(<30000)表示总钱数,m(<25)为希望购买物品的个数。)
背包的种类:
背包分为01背包,多重背包以及完全背包这三种基本模型,其他的背包问题都是从这3种背包中延申出来的。
完全背包的模板题面是这样的:设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以无限选取),使其重量的和小于等于M,而价值的和为最大。
int dp[MAXV];
int main(){
int n;
cin >> n;
int A[n];
for(int i=1; i <= n; i++){
cin >> A[i];
}
int ans = -1;
for(int i=1; i <= n; i++){
dp[i] = 1;
for(int j=1; j < i; j++){
cout << f[m] << endl;
return 0;
}
线性动态规划
//数塔
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
数据范围
1≤n≤500,
−10000≤三角形中的整数≤10000
s -= k;
k *= 2;
}
if (s > 0)
{
cnt ++ ;
v[cnt] = a * s;
w[cnt] = b * s;
}
}
n = cnt;
for (int i = 1; i <= n; i ++ )
for (int j = m; j >= v[i]; j -- )
f[j] = max(f[j], f[j - v[i]] + w[i]);
从第2行到第m+1行,第jj行给出了编号为j-1的物品的基本数据,每行有2个非负整数v p(其中vv表示该物品的价格(v≤10000),p表示该物品的重要度(1-5)
输出格式
1个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<100000000)。
输入:
1000 5
800 2
400 5
动态规划
装箱问题(01背包):
有一个箱子容量为VV(正整数,0≤V≤20000),同时有n个物品(0<n≤30,每个物品有一个体积(正整数)。要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
24 6
8 3 12 7 9 7
输出:0
#include<iostream>
#include<cstdio>
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
数据范围
0<N,V≤100
0<vi,wi,si≤100
输入样例
4 5
1 2 3
2Байду номын сангаас4 1
3 4 3
4 5 2
输出样例:
10
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n,m;
cin >> n >> m;
for(int i=1; i <= m; i++){
cin >> a[i] >> b[i];
}
for(int i=1; i <=m; i++){
for(int j=n; j >= a[i]; j--){
f[j] = max(f[j],f[j-a[i]]+b[i]);
}
for(int i=1; i <= n; i++){
for(int j=0; j <= m; j++){
for(int k=0; k <= s[i] && k*v[i] <= j; k++){
f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
}
}
}
cout << f[n][m];
}
}
cout<<v-f[v];
return 0;}
f[j]=max(f[j],f[j-w[i]]+w[i]);
f[j]为:当总容量为j时,不放第i件物品,所能装的最大体积。
f[j-w[i]]+w[i]为:当总容量为j时,放了第i件物品后,所能装的最大体积。(即j减去第i件物品体积的容量能装的最大体积+第i件物品的体积。w[i]为第i件物品体积)
return 0;
}
多重背包2
有 N 种物品和一个容量是 V 的背包。
第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
数据范围
0<N≤1000
0<V≤2000
0<vi,wi,si≤2000
提示:
本题考查多重背包的二进制优化方法。
cin >> A[i];
}
dp[0] = A[0];
for(int i=1; i < n; i++){
dp[i] = max(A[i],dp[i-1]+A[i]);
}
sort(dp,dp+n);
cout << dp[n-1] << endl;
return 0;
}
6
-2 11 -4 13 -5 -2
输出:20
}}
cout << f[n];
return 0;}
题目描述
金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用整数1-5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是整数元)。他希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。
const int maxn = 110;
int n,m;
int v[maxn],w[maxn],s[maxn];
int f[maxn][maxn];
int main(){
cin >> n >> m;
for(int i=1; i <= n; i++){
cin >> v[i] >> w[i] >> s[i];
输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例:
10
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 12010, M = 2010;
int n, m;
int v[N], w[N];
int f[M];
int main()
{
cin >> n >> m;
int cnt = 0;
for (int i = 1; i <= n; i ++ )
{
int a, b, s;
cin >> a >> b >> s;
int k = 1;
while (k <= s)
{
cnt ++ ;
v[cnt] = a * k;
w[cnt] = b * k;
int main(){
cin >> n;
int a[n][n];
fill(dp[0],dp[0]+MAXV*MAXV,0);
for(int i=0 ; i < n; i++){
for(int j=0; j <= i; j++){
cin >> a[i][j];
}
}
for(int i=0; i < n; i++){
dp[n-1][i] = a[n-1][i];
}
for(int i=n-1; i >=0; i--){
for(int j=0; j <= i; j++){
dp[i][j] = max(dp[i+1][j],dp[i+1][j+1]) + a[i][j];
}
}
cout << dp[0][0] << endl;
return 0;
}
②
//最大连续子序列和
}
for(int i=1; i <= m; i++){
for(int j=n; j >= k[i]; j--){
f[j] = max(f[j],f[j-k[i]]+k[i]*v[i]);
}
}
cout << f[n];
return 0;
}
多重背包
有N种物品和一个容量是V的背包。
第ii种物品最多有sisi件,每件体积是vivi,价值是wiwi。
完全背包
[无限量]的采摘药输入:
70 3
71 100
69 1
1 2
输出:140
每个数组在满足条件,可以遍历多次
#include<iostream>
#include<algorithm>
using namespace std;
int f[100001];
int a[10001],b[10001];
int main(){
输入样例:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例:
30
#include<iostream>
#include<algorithm>
const int MAXV = 10010;
using namespace std;
int dp[MAXV][MAXV];
int main(){
int n;
if(A[i] > A[j] && (dp[j] + 1) > dp[i]){
dp[i] = dp[j] + 1;
}
}
ans = max(ans,dp[i]);
}
cout << ans << endl;
return 0;
}
④
//最长公共子序列
给定两个长度分别为N和M的字符串A和B,求既是A的子序列又是B的子序列的字符串长度最长是多少。
using namespace std;
int f[20005],w[35];
int main()
{
int v,n;
cin>>v>>n;
for(int i=1;i<=n;i++)cin>>w[i];
for(int i=1;i<=n;i++){
for(int j=v;j>=w[i];j--){
f[j]=max(f[j],f[j-w[i]]+w[i]);
300 5
400 3
200 2
输出:
3900
#include<bits/stdc++.h>
using namespace std;
int f[30010],k[30],v[30];
int n,m;
int main(){
cin >> n >> m;
for(int i=1; i<= m; i++){
cin >> k[i] >> v[i];
//最长不下降子序列
给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。
数据范围
1≤N≤1000,
−10^9≤数列中的数≤10^9
输入样例:
7
3 1 2 1 8 5 6
输出样例:
4
#include<iostream>
const int MAXV = 10010;
using namespace std;
int n,m;
cin >> n >> m;
for(int i=1; i <= m; i++){
cin >> a[i] >> b[i];
}
for(int i=1; i<=m; i++){
for(int j=a[i]; j <=n; j++){
f[j] = max(f[j],f[j-a[i]]+b[i]);
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXV = 10010;
int A[MAXV],dp[MAXV];
int main(){
int n;
cin >> n;
for(int i=0; i < n; i++){
数据范围
1≤N≤1000,
输入样例:
4 5
acbd
abedc
输出样例:
3
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1010;
char A[maxn],B[maxn];
}
}
cout << f[n];
return 0;
}
01背包
实现代码:采药-传送门
输入:
70 3
71 100
69 1
1 2
输出:3
每个数组遍历一遍
#include<iostream>
#include<algorithm>
using namespace std;
int a[101],b[101];
int f[10001];
设第jj件物品的价格为v_[j],重要度为w_[j],共选中了k件物品,编号依次为j_1,j_2,…,j_k,则所求的总和为:
w_[j_k]v[ j1 ]×w[ j1 ]+v[ j2 ]×w[ j2 ]+…+v[ jk ]×w[ jk ]。
请你帮助金明设计一个满足要求的购物单。
输入格式
第一行,为2个正整数,用一个空格隔开:n m(其中N(<30000)表示总钱数,m(<25)为希望购买物品的个数。)
背包的种类:
背包分为01背包,多重背包以及完全背包这三种基本模型,其他的背包问题都是从这3种背包中延申出来的。
完全背包的模板题面是这样的:设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以无限选取),使其重量的和小于等于M,而价值的和为最大。
int dp[MAXV];
int main(){
int n;
cin >> n;
int A[n];
for(int i=1; i <= n; i++){
cin >> A[i];
}
int ans = -1;
for(int i=1; i <= n; i++){
dp[i] = 1;
for(int j=1; j < i; j++){
cout << f[m] << endl;
return 0;
}
线性动态规划
//数塔
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
数据范围
1≤n≤500,
−10000≤三角形中的整数≤10000
s -= k;
k *= 2;
}
if (s > 0)
{
cnt ++ ;
v[cnt] = a * s;
w[cnt] = b * s;
}
}
n = cnt;
for (int i = 1; i <= n; i ++ )
for (int j = m; j >= v[i]; j -- )
f[j] = max(f[j], f[j - v[i]] + w[i]);
从第2行到第m+1行,第jj行给出了编号为j-1的物品的基本数据,每行有2个非负整数v p(其中vv表示该物品的价格(v≤10000),p表示该物品的重要度(1-5)
输出格式
1个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<100000000)。
输入:
1000 5
800 2
400 5
动态规划
装箱问题(01背包):
有一个箱子容量为VV(正整数,0≤V≤20000),同时有n个物品(0<n≤30,每个物品有一个体积(正整数)。要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
24 6
8 3 12 7 9 7
输出:0
#include<iostream>
#include<cstdio>
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
数据范围
0<N,V≤100
0<vi,wi,si≤100
输入样例
4 5
1 2 3
2Байду номын сангаас4 1
3 4 3
4 5 2
输出样例:
10
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n,m;
cin >> n >> m;
for(int i=1; i <= m; i++){
cin >> a[i] >> b[i];
}
for(int i=1; i <=m; i++){
for(int j=n; j >= a[i]; j--){
f[j] = max(f[j],f[j-a[i]]+b[i]);
}
for(int i=1; i <= n; i++){
for(int j=0; j <= m; j++){
for(int k=0; k <= s[i] && k*v[i] <= j; k++){
f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
}
}
}
cout << f[n][m];
}
}
cout<<v-f[v];
return 0;}
f[j]=max(f[j],f[j-w[i]]+w[i]);
f[j]为:当总容量为j时,不放第i件物品,所能装的最大体积。
f[j-w[i]]+w[i]为:当总容量为j时,放了第i件物品后,所能装的最大体积。(即j减去第i件物品体积的容量能装的最大体积+第i件物品的体积。w[i]为第i件物品体积)
return 0;
}
多重背包2
有 N 种物品和一个容量是 V 的背包。
第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
数据范围
0<N≤1000
0<V≤2000
0<vi,wi,si≤2000
提示:
本题考查多重背包的二进制优化方法。
cin >> A[i];
}
dp[0] = A[0];
for(int i=1; i < n; i++){
dp[i] = max(A[i],dp[i-1]+A[i]);
}
sort(dp,dp+n);
cout << dp[n-1] << endl;
return 0;
}
6
-2 11 -4 13 -5 -2
输出:20
}}
cout << f[n];
return 0;}
题目描述
金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用整数1-5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是整数元)。他希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。
const int maxn = 110;
int n,m;
int v[maxn],w[maxn],s[maxn];
int f[maxn][maxn];
int main(){
cin >> n >> m;
for(int i=1; i <= n; i++){
cin >> v[i] >> w[i] >> s[i];
输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例:
10
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 12010, M = 2010;
int n, m;
int v[N], w[N];
int f[M];
int main()
{
cin >> n >> m;
int cnt = 0;
for (int i = 1; i <= n; i ++ )
{
int a, b, s;
cin >> a >> b >> s;
int k = 1;
while (k <= s)
{
cnt ++ ;
v[cnt] = a * k;
w[cnt] = b * k;