大家好,我是wangmy。
众所周知动态规划将原问题分解成若干个子问题,再把子问题分解成若干更多子问题。先求解子问题,再从这些子问题的解得到原问题的解。
今天我给大家分享一下动态规划的几道题和参考代码。
数字三角形
题目描述(Description)
编辑
输入格式(Format Input)
第一行一个整数N(<=1000),表示三角形总共有几行 第二至第N+1行,给出这个数字三角形
输出格式(Format Output)
一个整数,表示一路上所有数的最大和,结果不会超过int64
输入样例(Sample Input)
4 1 3 2 4 10 1 4 3 2 20
输出样例(Sample Output)
24
限制(Restrictions)
时间限制(Time Limit): 1000 ms
内存限制(Memory Limit): 65536 KB
参考代码:
#include<bits/stdc++.h>
using namespace std;
//状态 f[i][j]:(i,j)的最大值
//转移方程式:f[i][j]=max(f[i-1][j],f[i-1][j-1])+a[i][j]
long long n,a[1010][1010],f[1010][1010];
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
scanf("%lld",&a[i][j]);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
f[i][j]=max(f[i-1][j],f[i-1][j-1])+a[i][j];
}
}
long long ans=0;
for(int i=1;i<=n;i++)
{
if(f[n][i]>ans)
{
ans=f[n][i];
}
}
printf("%lld",ans);
return 0;
}
最长上升子序列
题目描述(Description)
给定一个长度为 N 的整数序列 A
找到一组最长的整数序列 x 满足:
1 <= x1 < x2 < ... < xk <= N
A[x1] < A[x2] < ... < A[xk]
即寻找 A 的一个最长子序列,满足:
该子序列中每个元素递增
输入格式(Format Input)
第一行一个整数N(N<=1000) 表示长度,第二行 N个数 A[i]表示序列里面的数,每个数不超过int范围。
输出格式(Format Output)
一行 表示最长递增子序列的长度
输入样例(Sample Input)
6 1 6 2 5 4 7
输出样例(Sample Output)
4
限制(Restrictions)
时间限制(Time Limit): 1000 ms
内存限制(Memory Limit): 65536 KB
参考代码:
#include<bits/stdc++.h>
using namespace std;
//f[i]以a[i]结尾的最大上升子序列长度
//f[i] = max(f[i], f[j] + 1), j < i, a[j] < a[i]
int n, a[1010], f[1010];
int main(){
cin >> n;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i++){
//赋初始值
f[i] = 1;
for(int j = 1; j < i; j++){
if(a[j] < a[i]) f[i] = max(f[i], f[j] + 1);
}
}
int ans = 0;
for(int i = 1; i <= n; i++)
if(ans < f[i]) ans = f[i];
cout << ans;
return 0;
}
最长公共子序列
题目描述(Description)
给定两个整数序列 A 和 B
序列中每个数都在int范围之内
寻找一个最长的整数序列 X,满足:
X 是 A 的子序列
X 是 B 的子序列
输入格式(Format Input)
第一行:序列A的长度 第二行:给出序列A 第三行:序列B的长度 第四行:给出序列B
长度<=1000
输出格式(Format Output)
只有一行:表示最长的公共子序列的长度
输入样例(Sample Input)
6
1 6 2 5 4 7
7
0 1 2 5 5 2 7
输出样例(Sample Output)
4
限制(Restrictions)
时间限制(Time Limit): 1000 ms
内存限制(Memory Limit): 65536 KB
参考代码:
#include<bits/stdc++.h>
using namespace std;
int n, m, a[1001], b[1001], dp[1001][1001];
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
cin >> m;
for(int i = 1; i <= m; i++) scanf("%d", &b[i]);
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(a[i] == b[j]){
dp[i][j] = dp[i-1][j-1] + 1;
}
else{
if(dp[i][j-1] > dp[i-1][j])
dp[i][j] = dp[i][j-1];
else
dp[i][j] = dp[i-1][j];
}
}
}
cout << dp[n][m];
return 0;
}
装箱问题
题目描述(Description)
有一个箱子容量为V(正整数,0 ≤ V ≤ 20000),同时有n个物品(0 < n ≤ 30),每个物品有一个体积(正整数)。要求从n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入格式(Format Input)
输入有若干行。第一行:一个整数,表示箱子容量V;第二行:一个整数,表示物品个数n;接下来n行,分别表示这n个物品的各自体积。
输出格式(Format Output)
输出只有一行数据,该行只有一个数,表示最小的箱子剩余空间。
输入样例(Sample Input)
24 6 8 3 12 7 9 7
输出样例(Sample Output)
0
限制(Restrictions)
时间限制(Time Limit): 1000 ms
内存限制(Memory Limit): 65536 KB
参考代码:
#include<bits/stdc++.h>
using namespace std;
int m,n;// m即箱子容量V
int f[20010];
int w[40];
int main(){
int i,j;
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++){
scanf("%d",&w[i]);
}
for(i=1;i<=n;i++){
for(j=m;j>=w[i];j--){
if(f[j]<f[j-w[i]]+w[i]){
f[j]=f[j-w[i]]+w[i];
}
}
}
printf("%d\n",m-f[m]);
}
今天的分享到此结束,我们下次再见。(希望大家有自己的思考,不要一味着抄代码)