目录
经典DP问题总结(1)——硬币问题、最长公共子序列、斐波拉契数列、整除子序列问题:https://blog.csdn.net/qq_41895747/article/details/103931625
1.矩阵链乘法
Matrix-chain Multiplication
The goal of the matrix-chain multiplication problem is to find the most efficient way to multiply given $n$ matrices $M_1, M_2, M_3,...,M_n$.
Write a program which reads dimensions of $M_i$, and finds the minimum number of scalar multiplications to compute the maxrix-chain multiplication $M_1M_2...M_n$.
Input
In the first line, an integer $n$ is given. In the following $n$ lines, the dimension of matrix $M_i$ ($i = 1...n$) is given by two integers $r$ and $c$ which respectively represents the number of rows and columns of $M_i$.
扫描二维码关注公众号,回复: 8655395 查看本文章Output
Print the minimum number of scalar multiplication in a line.
Constraints
$1 \leq n \leq 100$
$1 \leq r, c \leq 100$
Sample Input 1
6 30 35 35 15 15 5 5 10 10 20 20 25Sample Output 1
15125
Source: https://onlinejudge.u-aizu.ac.jp/problems/ALDS1_10_B
题解:https://www.cnblogs.com/fsmly/p/10228767.html
感觉技巧性较强
//矩阵链乘法
#include <iostream>
#include <algorithm>
using namespace std;
const int N=100;
int main(){
int n,p[N+1],m[N+1][N+1];//m代表所需乘法运算的最小次数
cin>>n;
for(int i=1;i<=n;i++)
cin>>p[i-1]>>p[i];//存储矩阵的行数
for(int i=1;i<=n;i++)
m[i][i]=0; //初始化所需乘法运算所需最小次数
for(int l=2;l<=n;l++){
for(int i=1;i<=n-l+1;i++){
int j=i+l-1;
m[i][j]=(l<<21);//取一个无穷大的数
for(int k=i;k<=j-1;k++){
m[i][j]=min(m[i][j],m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]);
}
}
}
cout<<m[1][n]<<endl;
return 0;
}
2.0-1背包问题
https://blog.csdn.net/xp731574722/article/details/70766804
3.最长递增子序列
For a given sequence A=a0,a1,…,an−1, find the length of the longest increasing subsequnece (LIS) in A.
An increasing subsequence of A is defined by a subsequence ai0,ai1,…,aik where 0≤i0<i1<…<ik<n and ai0<ai1<…<aik.
Input
n a0 a1 : an−1In the first line, an integer n is given. In the next n lines, elements of A are given.
Output
The length of the longest increasing subsequence of A.
Constraints
1 ≤ n ≤ 100000
0 ≤ ai ≤ 109
Sample Input 1
5 5 1 3 2 4Sample Output 1
3Sample Input 2
3 1 1 1Sample Output 2
1
纯DP思路也不难,但会超时;所以采用DP+二分的思路,不会超时
注:lower_bound()的用法:https://blog.csdn.net/qq_40160605/article/details/80150252
//最长递增子序列
//DP+二分查找
#include <iostream>
#include <algorithm>
using namespace std;
static const int MAX=100000;
int main(){
int n;
cin>>n;
int A[MAX+1];
for(int i=0;i<n;i++)
cin>>A[i];
int L[MAX];//表示末尾数字的最小值
L[0]=A[0];
int length=1;//表示第i个元素最长递增子序列的长度
for(int i=1;i<n;i++){
if(L[length-1]<A[i]){
L[length++]=A[i];//将A[i]添加到末尾,并将length加1
}else{
*lower_bound(L,L+length,A[i])=A[i];//二分查找A[i],返回A[i]的地址
}
}
cout<<length<<endl;
return 0;
}