经典DP问题总结(2)——矩阵链乘法、0-1背包问题、最长递增子序列、最大正方形

目录

1.矩阵链乘法

2.0-1背包问题

3.最长递增子序列

参考


经典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 25

Sample 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−1

In 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
4

Sample Output 1

3

Sample Input 2

3
1
1
1

Sample Output 2

1

Source: https://onlinejudge.u-aizu.ac.jp/problems/DPL_1_D

纯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;
} 

参考

https://www.zhihu.com/question/23995189

发布了228 篇原创文章 · 获赞 76 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_41895747/article/details/103955401