[USACO17JAN]Subsequence Reversal

嘟嘟嘟

 

这题刚开始是什么思路也没有,关键是不知道怎么解决序列反转的问题。

然后我就想到如果暴力反转一个序列的话,实际上就是不断交换数组中的两个数ai和aj,同时要满足交换的数不能交叉。

然后又看了一眼(岂止一眼)题解,因为ai <= 50,所以令dp[i][j][L][R]表示区间[i, j],min(ak) >= L, max(ak) <= R时,反转一次的最长不下降子序列。

显然是一个区间dp,那么[i, j]可以从[i + 1, j],[i, j - 1]或是[i + 1, j - 1]转移过来,所以L,R也只可能从ai+1,aj-1转移过来。然后还要考虑交换或者不交换的情况。代码就是dp式了,这里就不写了

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 55;
21 inline ll read()
22 {
23   ll ans = 0;
24   char ch = getchar(), last = ' ';
25   while(!isdigit(ch)) {last = ch; ch = getchar();}
26   while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
27   if(last == '-') ans = -ans;
28   return ans;
29 }
30 inline void write(ll x)
31 {
32   if(x < 0) x = -x, putchar('-');
33   if(x >= 10) write(x / 10);
34   putchar(x % 10 + '0');
35 }
36 
37 int n, a[maxn];
38 int dp[maxn][maxn][maxn][maxn];
39 
40 int main()
41 {
42   n = read();
43   for(int i = 1; i <= n; ++i) a[i] = read(), dp[i][i][a[i]][a[i]] = 1;
44   for(int len = 2; len <= n; ++len)
45     for(int i = 1; i + len - 1 <= n; ++i)
46       {
47     int j = i + len - 1;
48     for(int l = 1; l <= 50; ++l)
49       for(int L = 1; L + l - 1 <= 50; ++L)
50         {
51           int R = L + l - 1;
52           dp[i][j][L][R] = max(dp[i][j][L][R], max(dp[i + 1][j][L][R], dp[i][j - 1][L][R]));
53           dp[i][j][L][R] = max(dp[i][j][L][R], max(dp[i][j][L + 1][R], dp[i][j][L][R - 1]));
54           dp[i][j][min(L, a[i])][R] = max(dp[i][j][min(L, a[i])][R], dp[i + 1][j][L][R] + (a[i] <= L));
55           dp[i][j][L][max(R, a[j])] = max(dp[i][j][L][max(R, a[j])], dp[i][j - 1][L][R] + (a[j] >= R));
56           dp[i][j][min(L, a[j])][R] = max(dp[i][j][min(L, a[j])][R], dp[i + 1][j - 1][L][R] + (a[j] <= L));  //一下三行是ai和aj交换
57           dp[i][j][L][max(R, a[i])] = max(dp[i][j][L][max(R, a[i])], dp[i + 1][j - 1][L][R] + (a[i] >= R));
58           dp[i][j][min(L, a[j])][max(R, a[i])] = max(dp[i][j][min(L, a[j])][max(R, a[i])], dp[i + 1][j - 1][L][R] + (a[i] >= R) + (a[j] <= L));
59         }
60       }
61   write(dp[1][n][1][50]), enter;
62   return 0;
63 }
View Code

 

posted @ 2018-10-22 19:51  mrclr  阅读(291)  评论(0编辑  收藏  举报