Codeforces 813D Two Melodies(维护转移来源的DP)

D. Two Melodies
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Alice is a beginner composer and now she is ready to create another masterpiece. And not even the single one but two at the same time!

Alice has a sheet with n notes written on it. She wants to take two such non-empty non-intersecting subsequences that both of them form a melody and sum of their lengths is maximal.

Subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements.

Subsequence forms a melody when each two adjacent notes either differs by 1 or are congruent modulo 7.

You should write a program which will calculate maximum sum of lengths of such two non-empty non-intersecting subsequences that both of them form a melody.

Input
The first line contains one integer number n (2 ≤ n ≤ 5000).

The second line contains n integer numbers a1, a2, …, an (1 ≤ ai ≤ 105) — notes written on a sheet.

Output
Print maximum sum of lengths of such two non-empty non-intersecting subsequences that both of them form a melody.

Examples
input
4
1 2 4 5
output
4
input
6
62 22 60 61 48 49
output
5
Note
In the first example subsequences [1, 2] and [4, 5] give length 4 in total.

In the second example subsequences [62, 48, 49] and [60, 61] give length 5 in total. If you choose subsequence [62, 61] in the first place then the second melody will have maximum length 2, that gives the result of 4, which is not maximal.

题目大意

  有一个长度为N(2N5000)的序列,要求从中选择两个相互独立的子序列,每个子序列相邻元素之间差1或对于7同余,使得这两个字序列的长度之和最大。

解题思路

  首先很容易相当dp[i][j]表示两个字序列分别以i,j结尾的最长长度。转移就是枚举下一个位置,总时间复杂度为O(N3),显然无法通过。
  考虑固定一个i,则对每个j来说,只要考虑dp[i][k](k<j)中同余的长度最大的,值小1的长度最大的,值大1的长度最大的。所以我我们可以对于每个i,维护每个同余值的长度最大值,和每个值的长度最大值,并在转移的过程中更新,O(1)的实现转移。总时间复杂度O(N2)

AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cstdlib>
#include <cmath>
#include <map>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))

const int MAXN=5000+3;
const int MAXA=100000+3;
int N, a[MAXN];
int dp[MAXN][MAXN];//表示一个序列以i结尾,一个序列以j结尾的最大长度
int max_mod[10], max_a[MAXA];//表示此时a[j]%7为各个值的最长序列,表示a[j]为各个值的最长序列

int main()
{
    scanf("%d", &N);
    for(int i=1;i<=N;++i)
        scanf("%d", &a[i]);
    int ans=0;
    for(int i=0;i<=N;++i)
    {
        for(int j=0;j<7;++j)
            max_mod[j]=0;
        for(int j=1;j<=N;++j)
            max_a[a[j]]=0;
        for(int j=1;j<i;++j)//预处理出此时各个情况的最大长度
        {
            max_mod[a[j]%7]=max(max_mod[a[j]%7], dp[i][j]);
            max_a[a[j]]=max(max_a[a[j]], dp[i][j]);
        }        
        for(int j=i+1;j<=N;++j)//进行转移并更新维护的值
        {
            dp[i][j]=max(max(max_a[a[j]-1], max_a[a[j]+1]), max(max_mod[a[j]%7], dp[i][0]))+1;
            dp[j][i]=dp[i][j];
            max_mod[a[j]%7]=max(max_mod[a[j]%7], dp[i][j]);
            max_a[a[j]]=max(max_a[a[j]], dp[i][j]);
            ans=max(ans, dp[i][j]);
        }

    }
    printf("%d\n", ans);

    return 0;
}
阅读更多
版权声明:转载请注明出处:http://blog.csdn.net/yasola,谢谢 https://blog.csdn.net/Yasola/article/details/78161291
文章标签: 算法 ACM DP Codeforces
个人分类: 算法 DP
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭