算法笔记 上机训练实战指南 第11章 提高篇(5)--动态规划专题 学习笔记

11.2 最大连续子序列和

PAT A1007 Maximum Subsequence Sum (25分)

Given a sequence of K integers { N1​​, N2​​, ..., NK​​ }. A continuous subsequence is defined to be { Ni​​, Ni+1​​, ..., Nj​​ } where 1. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (≤). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:

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

Sample Output:

10 1 4
#include<cstdio>
const int maxn = 10010;
int A[maxn],dp[maxn],s[maxn] = {0};
int main(){
    int n;
    bool flag = false;
    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]);
        return 0; 
    }
    //边界 
    dp[0] = A[0];
    for(int i = 1; i < n;i++){
        //状态转移方程
        if(dp[i-1] + A[i] > A[i]){
            dp[i] = dp[i-1] + A[i]; 
            s[i] = s[i-1];
        }else{
            dp[i] = A[i];
            s[i] = i;
        }
    }
    //dp[i]存放以A[i]结尾的连续序列的最大和,需要遍历i得到最大的才是结果
    int k = 0;
    for(int i = 1;i < n;i++){
        if(dp[i] > dp[k]){
            k = i;
        }
    } 
    printf("%d %d %d\n",dp[k],A[s[k]],A[k]);
    return 0;
}

 11.3 最长不下降子序列(LIS)

PAT A1045 Favorite Color Stripe (30分)

Eva is trying to make her own color stripe out of a given one. She would like to keep only her favorite colors in her favorite order by cutting off those unwanted pieces and sewing the remaining parts together to form her favorite color stripe.

It is said that a normal human eye can distinguish about less than 200 different colors, so Eva's favorite colors are limited. However the original stripe could be very long, and Eva would like to have the remaining favorite stripe with the maximum length. So she needs your help to find her the best result.

Note that the solution might not be unique, but you only have to tell her the maximum length. For example, given a stripe of colors {2 2 4 1 5 5 6 3 1 1 5 6}. If Eva's favorite colors are given in her favorite order as {2 3 1 5 6}, then she has 4 possible best solutions {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, and {2 2 3 1 1 5 6}.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤) which is the total number of colors involved (and hence the colors are numbered from 1 to N). Then the next line starts with a positive integer M (≤) followed by M Eva's favorite color numbers given in her favorite order. Finally the third line starts with a positive integer L (≤) which is the length of the given stripe, followed by L colors on the stripe. All the numbers in a line a separated by a space.

Output Specification:

For each test case, simply print in a line the maximum length of Eva's favorite stripe.

Sample Input:

6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

Sample Output:

7
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxc = 210;
const int maxn = 10010;
int HashTable[maxc];
int A[maxn],dp[maxn];
int main(){
    int n,m,x;
    scanf("%d%d",&n,&m);
    memset(HashTable,-1,sizeof(HashTable));
    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];
        }
    }
    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\n",ans);
    return 0;
}

 

11.4 最长公共子序列(LCS)

PAT A1045 Favorite Color Stripe (30分)

Eva is trying to make her own color stripe out of a given one. She would like to keep only her favorite colors in her favorite order by cutting off those unwanted pieces and sewing the remaining parts together to form her favorite color stripe.

It is said that a normal human eye can distinguish about less than 200 different colors, so Eva's favorite colors are limited. However the original stripe could be very long, and Eva would like to have the remaining favorite stripe with the maximum length. So she needs your help to find her the best result.

Note that the solution might not be unique, but you only have to tell her the maximum length. For example, given a stripe of colors {2 2 4 1 5 5 6 3 1 1 5 6}. If Eva's favorite colors are given in her favorite order as {2 3 1 5 6}, then she has 4 possible best solutions {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, and {2 2 3 1 1 5 6}.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤) which is the total number of colors involved (and hence the colors are numbered from 1 to N). Then the next line starts with a positive integer M (≤) followed by M Eva's favorite color numbers given in her favorite order. Finally the third line starts with a positive integer L (≤) which is the length of the given stripe, followed by L colors on the stripe. All the numbers in a line a separated by a space.

Output Specification:

For each test case, simply print in a line the maximum length of Eva's favorite stripe.

Sample Input:

6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

Sample Output:

7
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxc = 210;
const int maxn = 10010;
int A[maxc],B[maxn],dp[maxc][maxn];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d",&A[i]);
    }
    int L;
    scanf("%d",&L);
    for(int i = 1; i <= L;i++){
        scanf("%d",&B[i]);
    }
    //边界
    for(int i=0;i<=m;i++){
        dp[i][0] = 0;
    } 
    for(int j=0;j<=L;j++){
        dp[0][j] = 0;
    }
    for(int i = 1; i <= m;i++){
        for(int j=1;j <= L;j++){
            int MAX = max(dp[i-1][j],dp[i][j-1]);
            if(A[i] == B[j]){
                dp[i][j] = MAX + 1;
            }else{
                dp[i][j] = MAX;
            }
        }
    }
    printf("%d\n",dp[m][L]);
    return 0;
}

 PAT A1040 Longest Symmetric String (25分) 

Given a string, you are supposed to output the length of the longest symmetric sub-string. For example, given Is PAT&TAP symmetric?, the longest symmetric sub-string is s PAT&TAP s, hence you must output 11.

Input Specification:

Each input file contains one test case which gives a non-empty string of length no more than 1000.

Output Specification:

For each test case, simply print the maximum length in a line.

Sample Input:

Is PAT&TAP symmetric?

Sample Output:

11
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 1010;
string S; 
int dp[maxn][maxn];
int main(){
    getline(cin,S);    
    int len = S.size(),ans = 1;
    memset(dp,0,sizeof(dp));
    for(int i = 0;i < len;i++){
        dp[i][i] = 1;
        if(i < len -1){
            if(S[i] == S[i+1]){
                dp[i][i+1] = 1;
                ans = 2;
            }
        }
    }
    
    for(int L = 3; L <= len;L++){
        for(int i=0;i+L-1<len;i++){
            int j = i + L - 1;
            if(S[i] == S[j] && dp[i+1][j-1] == 1){
                dp[i][j] = 1;
                ans = L;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

11.7 背包问题

PAT A1068 Find More Coins (30分)

Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special requirement of the payment: for each bill, she must pay the exact amount. Since she has as many as 1 coins with her, she definitely needs your help. You are supposed to tell her, for any given amount of money, whether or not she can find some coins to pay for it.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive numbers: N (≤, the total number of coins) and M (≤, the amount of money Eva has to pay). The second line contains N face values of the coins, which are all positive numbers. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the face values V1​​V2​​Vk​​ such that V1​​+V2​​++Vk​​=M. All the numbers must be separated by a space, and there must be no extra space at the end of the line. If such a solution is not unique, output the smallest sequence. If there is no solution, output "No Solution" instead.

Note: sequence {A[1], A[2], ...} is said to be "smaller" than sequence {B[1], B[2], ...} if there exists k1 such that A[i]=B[i] for all i<k, and A[k] < B[k].

Sample Input 1:

8 9
5 9 8 7 2 3 4 1

Sample Output 1:

1 3 5

Sample Input 2:

4 8
7 2 4 3

Sample Output 2:

No Solution
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 10010;
const int maxm = 110;
int w[maxn],dp[maxn]={0};
int choice[maxn][maxm],flag[maxn];
bool cmp(int a,int b){
    return a>b;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1;i<=n;i++){
        scanf("%d",&w[i]);
    }
    sort(w+1,w+1+n,cmp);
    for(int i = 1; i <= n; i++){
        for(int v=m;v >= w[i];v--){
            if(dp[v] <= dp[v-w[i]] + w[i]){
                dp[v] = dp[v-w[i]] + w[i];
                choice[i][v] = 1;
            }else{
                choice[i][v] = 0;
            }
        }
    }
    if(dp[m] != m){
        printf("No Solution");
    }else{
        int k=n, num = 0, v=m;
        while(k >= 0){
            if(choice[k][v] == 1){
                flag[k] = true;
                v = v - w[k];
                num++;
            }else{
                flag[k] = false;
            }
            k--;
        }
        for(int i = n; i >= 1; i--){
            if(flag[i] == true){
                printf("%d",w[i]);
                num--;
                if(num > 0)
                    printf(" ");
            }
        }
    }
    return 0;
} 

 




posted @ 2020-02-10 23:57  程序员小应  阅读(194)  评论(0编辑  收藏  举报