动态规划 算法笔记

本文详细探讨了动态规划的概念,通过数塔问题、最大连续子序列和、最长上升子序列、最长子序列、最长回文子串以及矩形嵌套等经典案例,深入解析动态规划的解题思路和实现方法。
摘要由CSDN通过智能技术生成

1.数塔问题
sum_max(top->bottom)

#include<bits/stdc++.h>
using namespace std;
int a[50][50]; 
int main(){
	int n;
	cin>>n; 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			cin>>a[i][j];
		}
	}
	int dp[50][50];
	for(int i=1;i<=n;i++){
		dp[n][i]=a[n][i];
	} 
	for(int i=n;i>=2;i--){
		for(int j=1;j<=i;j++){
			dp[i-1][j]=max(dp[i][j]+a[i-1][j],dp[i][j+1]+a[i-1][j]);
		}
	} 
	cout<<dp[1][1];
    return 0;
}
/*
5
5
8 3
12 7 16
4 10 11 6
9 5 3 9 4
*/

2.最大连续子序列和
http://codeup.cn/problem.php?cid=100000626&pid=0

#include<bits/stdc++.h>
using namespace std;
int n;
int a[10010];
int dp[10010];
int start[10010]; 
void get(int fu){
	if(fu==0){
		cout<<0<<" "<<a[0]<<" "<<a[n-1]<<endl;
	}
	else{
		dp[0]=a[0];start[0]=0;	
		for(int i=1;i<n;i++){
			dp[i]=max(dp[i-1]+a[i],a[i]);
			if(dp[i]==a[i])
			start[i]=i;
			else{
				start[i]=start[i-1];
			}
		}
		int maxi=-1,max_sum=-(1<<30);
		for(int i=0;i<n;i++){
			if(max_sum<dp[i]){
				max_sum=dp[i];
				maxi=i;
			}
		}
		cout<<max_sum<<" "<<a[start[maxi]]<<" "<<a[maxi]<<endl;
	}
}
int main(){
	while(1){
		cin>>n;
		if(n==0)
		break;
		int fu=0;
		for(int i=0;i<n;i++){
			cin>>a[i];
			if(a[i]>=0)
			fu=1;
		}
		get(fu);
	}
    return 0;
}
/*

*/

3.最长上升子序列
http://codeup.cn/problem.php?cid=100000627&pid=0

#include<bits/stdc++.h>
using namespace std;
int a[1009];
int dp[1009];
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	dp[0]=1;		
	int Max=1;
	for(int i=1;i<n;i++){
		Max=1;
		for(int j=0;j<i;j++){
			if(a[i]>a[j]&&(dp[j]+1)>Max){
				Max=dp[j]+1; 
			}
		}
		dp[i]=Max;
	}
	for(int i=0;i<n;i++)
	if(dp[i]>Max)
	Max=dp[i];
	cout<<Max;
    return 0;
}
/*

*/

4.最长子序列
http://codeup.cn/problem.php?cid=100000628&pid=0

//#include<bits/stdc++.h>
#include<iostream>;
#include<string>
using namespace std;
string a,b;
int dp[110][110];
int main(){
	while(cin>>a>>b){
		for(int i=0;i<=a.length();i++){
			dp[i][0]=0;
		}
		for(int j=0;j<=b.length();j++){
			dp[0][j]=0;
		}
		for(int i=1;i<=a.length();i++){
			for(int j=1;j<=b.length();j++){
				if(a[i-1]==b[j-1]){
					dp[i][j]=dp[i-1][j-1]+1;
				}
				else{
					dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
				}
			}
		}
		cout<<dp[a.length()][b.length()]<<endl;
	}
    return 0;
}
/*

*/

5.最长回文子串
http://codeup.cn/problem.php?cid=100000629&pid=0

#include<bits/stdc++.h>
using namespace std;
char input[5010];
int pos[5010];	
bool dp[5010][5010];
string toBig(char *a){
	char temp[5010];
	int tempInt=0;
	int cnt=0;
	for(int i=0;a[i]!='\0';i++){
		if(a[i]>='a'&&a[i]<='z'||a[i]>='A'&&a[i]<='Z'){
			pos[tempInt]=cnt;
			temp[tempInt++]=a[i];
		}
		else{
			pos[i]=i;
			cnt++;
		}
	}
	temp[tempInt]='\0';
	string re(temp);
	transform( re.begin(),re.end(),re.begin(),::toupper );
	return re;
}
void get(string a,int &l,int &r){
	int MaxL=1; 
	for(int i=0;i<a.length();i++){
		dp[i][i]=1;
	}
	for(int i=1;i<a.length();i++){
		if(a[i-1]==a[i]){
			dp[i-1][i]=1;
			if(MaxL<2){
				MaxL=2;
				l=i-1;
     	        r=i;
			}
		}
	}
	for(int L=3;L<=a.length();L++){
		//左端点为i时,右端点为i+L-1
		//cout<<L;
		for(int i=0;(i+L-1)<a.length();i++){
			if(a[i]==a[i+L-1]){
				dp[i][i+L-1]=dp[i+1][i+L-2];
				if(dp[i][i+L-1]==1){
					if(L>MaxL){
						MaxL=L;
						l=i;
						r=i+L-1;
					}
				}
			}
			else{
				dp[i][i+L-1]=0;
			}
		}
	}
	return ;
}
void rcv(int &l,int &r){
	l=l+pos[l];
	r=r+pos[r];
}
int main(){
	while(gets(input)!=NULL){
		string a=toBig(input); 
		int l=5010,r=5010;
		get(a,l,r);
		rcv(l,r);
		for(int i=l;i<=r;i++)
		   cout<<input[i];
		cout<<endl; 
	} 
    return 0;
}
/*

*/

6.矩形嵌套
http://codeup.cn/problem.php?cid=100000630&pid=0

#include<bits/stdc++.h>
using namespace std;
int N;
int n;
int Map[1010][1010];
int dp[1010];
struct rec{
	int a, b;
}r[1010];
bool In(rec x ,rec y){
	if( x.a<y.a&&x.b<y.b||x.a<y.b&&x.b<y.a )
	return true;
	else return false;
}
int DP(int i){
	if( dp[i]>0 )
	   return dp[i];
    int re=0;
    int temp=0;
	for(int j=0;j<n;j++){
		if(Map[i][j]==1){
			temp=DP(j)+1;
			if(temp>re){
				re=temp;
			}
		}
	}
	return re;
}
int main(){
	cin>>N;
	for(int times=0;times<N;times++){
		cin>>n;
		for(int j=0;j<n;j++){
			cin>>r[j].a>>r[j].b;
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){				
				if( In(r[j],r[i]) ){
					Map[i][j]=1;
				}
				else{
					Map[i][j]=-1;
				}
			}
		}
		int Max=0;
		for(int i=0;i<n;i++){
			dp[i]=0;
		}
		for(int i=0;i<n;i++){
			int pre=DP(i);
			if(Max<pre)
			Max=pre;
		}
		cout<<Max+1<<endl;
	}
    return 0;
}
/*

*/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值