1 基础知识
2 例题——拦截导弹
代码
#include <iostream>
using namespace std;
const int MAXN = 26;
int main(){
int n;
while(cin>>n && n){
int arr[MAXN],dp[MAXN],maxinum=0;
for(int i=0;i<n;i++){
cin>>arr[i];
dp[i]=1;
}
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
if(arr[i]<=arr[j]){
dp[i]=max(dp[i],dp[j]+1);
}
}
maxinum = max(maxinum,dp[i]);
}
cout<<maxinum<<endl;
}
return 0;
}
3 例题——最大上升子序列和
代码
#include <iostream>
using namespace std;
const int MAXN = 1001;
int main(){
int n;
while(cin>>n && n){
long long arr[MAXN],dp[MAXN],maxinum=0;
for(int i=0;i<n;i++){
cin>>arr[i];
dp[i]=arr[i];
}
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
if(arr[i]>arr[j]){
dp[i]=max(dp[i],dp[j]+arr[i]);
}
}
maxinum = max(maxinum,dp[i]);
}
cout<<maxinum<<endl;
}
return 0;
}
4 例题——合唱队形
思路:使用两个dp数组
代码
#include <iostream>
using namespace std;
const int MAXN=101;
int main(){
int N;
while(cin>>N){
int arr[MAXN],maxinum=0;
int dp1[MAXN]; // dp1[i]:从左到右,以arr[i]作为末尾的最长递增序列长度
int dp2[MAXN]; // dp2[j]:从右到左,以arr[j]作为末尾的最长递减序列长度
for(int i=0;i<N;i++){
cin>>arr[i];
dp1[i] = dp2[i] = 1;
}
for(int i=0;i<N;i++){
for(int j=0;j<i;j++){
if(arr[i]>arr[j]){
dp1[i] = max(dp1[i],dp1[j]+1);
}
}
}
for(int i=N-1;i>=0;i--){
for(int j=N-1;j>i;j--){
if(arr[i]>arr[j]){
dp2[i] = max(dp2[i],dp2[j]+1);
}
}
}
for(int i=0;i<N;i++)
maxinum = max(maxinum,dp1[i]+dp2[i]);
cout<<(N-maxinum+1)<<endl;
}
return 0;
}
5 例题——PAT1045
这题就是最长非递减序列例题之一,需要进行一下数据的预处理:
对于序列L,顺序遍历元素,若元素不在序列K中,则不作任何操作;若元素在序列K中,则将该元素在序列K中的位置作为新值添加到序列arr尾部。
题目便可转化为求arr序列的最长非递减序列的长度。
#include <iostream>
#include <map>
using namespace std;
const int MAXN=1e4+1;
map<int,int> myMap;
int dp[MAXN],arr[MAXN],num=0;
int main() {
int N,M,L,res=1;
cin>>N>>M;
for(int i=1; i<=M; i++) {
int elem;
cin>>elem;
myMap[elem]=i;
}
cin>>L;
for(int i=0; i<L; i++) {
int elem;
cin>>elem;
if(myMap.find(elem)!=myMap.end()) {
arr[num++]=myMap[elem];
}
}
fill(dp,dp+num,1);
for(int i=0; i<num; i++) {
for(int j=0; j<i; j++) {
if(arr[j]<=arr[i])
dp[i] = max(dp[i],dp[j]+1);
}
res = max(res, dp[i]);
}
cout<<res<<endl;
return 0;
}