PAT刷题之动态规划专题

Posted 辛勤的小码农^-^

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PAT刷题之动态规划专题相关的知识,希望对你有一定的参考价值。

PAT刷题之动态规划专题

活着真好!

1. 最大连续字段和 | 11.4

1.1模板

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn=10010;
int A[maxn],dp[maxn]; //A[i]存放序列,dp[i]以A[i]为结尾的连续序列的
int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&A[i]);
    }
    //边界 
    dp[0]=A[0];
    for(int i=1;i<n;i++){
        dp[i]=max(A[i],dp[i-1]+A[i]);
    }

    int k=0;
    for(int i=0;i<n;i++){
        if(dp[i]>dp[k]){
            k=i;
        }
    }
    printf("%d\\n",dp[k]);

    return 0;
}

//6
//-2 11 -4 13 -5 -2

//20

1.2 A1007 最大连续字段和

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn=10010;
int A[maxn],dp[maxn]; //A[i]存放序列,dp[i]以A[i]为结尾的连续序列的最大和 
int s[maxn]={0}; //s[i]表示 产生dp[i]的连续序列从a的哪一个元素开始  

int main(){
    int n;
    bool flag=false; //flag表示数组a中是否全小于0 
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&A[i]);
        if(A[i]>=0) flag=true; 
    }
    if(flag==false){
    	printf("0 %d %d\\n",A[0],A[n-1]);
    }
    //边界 
    dp[0]=A[0];
    for(int i=1;i<n;i++){
        if(A[i]<dp[i-1]+A[i]){  //输出ij最小的方案,故此情况的优先级更高 
        	dp[i]=dp[i-1]+A[i];
        	s[i]=s[i-1];
        }else{
        	dp[i]=A[i];
        	s[i]=i;
        }
    }

    int k=0;
    for(int i=0;i<n;i++){ 
        if(dp[i]>dp[k]){
            k=i;
        }
    }
    printf("%d %d %d\\n",dp[k],A[s[k]],A[k]);

    return 0;
}

/*10
-10 1 2 3 4 -5 -23 3 7 -21

10 1 4
 */

2. 最长不下降子序列 | 11.3

2.1 LIS模板

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn=100;
int A[maxn],dp[maxn];  //以A[i]结尾的最长不下降子序列

int main(){
 	int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&A[i]);
   }
    int ans=-1;
	for(int i=1;i<=n;i++){
		dp[i]=1;
		for(int j=1;j<i;j++){
			if(A[i]>=A[j]&&(dp[j]+1>dp[i])){
				dp[i]=dp[j]+1;
			}
		}
		ans=max(ans,dp[i]);
	} 
	printf("%d",ans);
	
	return 0;
} 

/*
 8
1 2 3 -9 3 9 0 11

5
*/

2.3 A1045最喜欢的颜色条(LIS)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxc=210;  //最大颜色数 
const int maxn=10010; //最大L
int HashTable[maxc]; //将喜欢的颜色序列映射为递增序列,不喜欢的颜色映射为1 
int A[maxn],dp[maxn];  //原数组和DP数组

int main()
{
	int n,m,x;
	scanf("%d",&m);
	memset(HashTable,-1,sizeof(HashTable));//整个数组初始化为-1
	for(int i=0;i<m;i++){
		scanf("%d",&x);
		HashTable[x]=i;  //将喜欢的颜色映射到递增序列 
	} 
	int L,num=0;
	scanf("%d",&L);
	for(int i=0;i<L;i++){
		scanf("%d",&x);
		if(HashTable[x]>=0){
			A[num++]=HashTable[x];
		}
	}
	
	//LIS模板
	int ans=-1;
	for(int i=0;i<num;i++){
		dp[i]=1;
		for(int j=0;j<i;j++){
			if(A[i]>=A[j]&&dp[j]+1>dp[i])
				dp[i]=dp[j]+1;
		}
		ans=max(ans,dp[i]);
	}
	 
	printf("%d",ans);
	
	return 0;
} 
/*
6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

7
*/

3. 最长公共子序列(LCS)|11.4

3.1 模板

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int N=200;
char A[N],B[N];
int dp[N][N]; //A的i号位和B的j号位之前的LCS长度(下标从1开始) 

int main(){
	int n;
	gets(A+1);
	gets(B+1);
	int lenA=strlen(A+1);
	int lenB=strlen(B+1);
	
	for(int i=0;i<=lenA;i++){
		dp[i][0]=0;
	}
	
	for(int i=0;i<=lenB;i++){
		dp[0][i]=0;
	}
	//状态转移方程
	for(int i=1;i<=lenA;i++){
		for(int j=1;j<=lenB;j++){
			if(A[i]==B[j]){
				dp[i][j]=dp[i-1][j-1]+1;
			}else{
				dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
			}
		}
	} 
	printf("%d\\n",dp[lenA][lenB]);
	
	return 0;
} 

/*
sadstory
adminsorry
6
*/

3.2 A1045最喜欢的颜色条(LCS)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxc=210;  //最大颜色数n
const int maxn=10010; //最大m
int A[maxc],B[maxn],dp[maxc][maxn];  //原数组和DP数组


int main(){
	int m,n;
	scanf("%d",&m);
	for(int i=0;i<m;i++){
		scanf("%d",&A[i]);
	}
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&B[i]);
	}
	
	for(int i=0;i<=m;i++){
		dp[i][0]=0;
	}
	
	for(int i=0;i<=n;i++){
		dp[0][i]=0;
	}
	//状态转移方程
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			if(A[i]==B[j]){ //允许重复值的出现 
				dp[i][j]=max(dp[i-1][j],dp[i][j-1])+1;
			}else{
				dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
			}
		}
	} 
	printf("%d\\n",dp[m][n]);
	
	return 0;
} 

/*
6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

7
*/

以上是关于PAT刷题之动态规划专题的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode刷题之动态规划(Java)

跟着chengyulala刷题之[kuangbin带你飞]之'并查集'专题/斜眼笑

动态规划经典题之编辑距离

LeetCode动态规划专题

算法题之动态规划

动态规划经典题之年终奖