• [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
  • 相关阅读:
    razor在App_Code中使用ActionLink无效的解决方案
    科技的进步会给人带来幸福么?
    C6000系列之C6455 DSP的EMIFA接口
    C6000系列之C6455DSP的GPIO模块
    C语言文件操作与例子
    C语言中fscanf函数读取double型浮点数的问题
    MATLAB读取CCS保存的数据
    CCS 3.3 操作C函数读写文件
    复数矩阵乘法C语言实现
    C6000系列之C6455DSP的中断系统
  • 原文地址:https://www.cnblogs.com/mrclr/p/9832141.html
Copyright © 2020-2023  润新知