uva 111 - History Grading

点击打开链接


题目意思:   给定一个正确的编号序列,然后对输入的每一组序列找最长公共子序列


解题思路:     动态规划

                       1:题目给定的n个数并不是表示当前位置的值就是Ai,而是表示第i个数放在第Ai个位置,看样列4 2 3 1,说明1放在第四位,2放在第二位,3放在第三位,4放在第一位。
                       2:题目就是要求出最长的公共子序列,由于题目的n最大才20,那么我们可以直接去枚举。假设现在枚举到Ai这个数,那么我们就求i之前的所以数能够和Ai构成连续的序列最大值dp[i],然后判断能否更新最大值(max_point < dp[i]),最后输出这个最大值即可。


代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
#define MAXN 25

int n;
int correct[25];//存储正确的顺序
int order[MAXN];//要求的顺序
int dp[MAXN];

void solve(){
    int max_point = 0;
    int pos_i , pos_j;//记录在correct数组中的位置
    dp[0] = 1;
    for(int i = 1 ; i < n ; i++){
        dp[i] = 1;//初始化为1
        for(int j = i-1 ; j >= 0 ;j--){//搜索i之前的数
            for(int k = 0 ; k < n ; k++){//去correct数组中找到order[i] 和order[j]的位置
                if(correct[k] == order[i]) pos_i = k;
                if(correct[k] == order[j]) pos_j = k;
            }
            if(pos_i > pos_j){//如果i在j后面说明是连续的,求dp[i]
                if(dp[j]+1 > dp[i]) dp[i] = dp[j]+1;
            }
        }
        if(max_point < dp[i]) max_point = dp[i];//更新max_point
    }
    printf("%d\n" , max_point);
}

int main(){
    //freopen("input.txt" , "r" , stdin);
    int m;
    scanf("%d" , &n);
    for(int i = 1 ; i <= n ; i++){
        scanf("%d" , &m) ;  correct[m-1] = i;//求出correct数组
    }
    while(scanf("%d" , &m) != EOF){
        order[m-1] = 1;
        for(int j = 2 ; j <= n ; j++) {
            scanf("%d" , &m) ; order[m-1] = j;//求出order数组
        }
        solve();
    }
    return 0;
}



更多详细信息请查看 java教程网 http://www.itchm.com/forum-59-1.html

猜你喜欢

转载自leili.iteye.com/blog/1629704
111