zoukankan      html  css  js  c++  java
  • HDU 6357.Hills And Valleys-动态规划(区间翻转l,r找最长非递减子序列)

    题意:给一串由n个数字组成的字符串,选择其中一个区间进行翻转,要求翻转后该字符串的最长非降子序列长度最长,输出这个最长非降子序列的长度以及翻转的区间的左右端点

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 100005;
    const int maxm = 22;
    int n, a[maxn], dp[maxn][maxm], b[maxm];
    int ans, ansl, ansr, l, r, cnt;
    int al[maxn][maxm], ar[maxn][maxm];
    char s[maxn];
     
    int solve()
    {
        for(int i = 0; i <= cnt; i++)
            dp[0][i] = 0;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= cnt; j++)
            {
                dp[i][j] = dp[i - 1][j];
                al[i][j] = al[i - 1][j];//al记录翻转的左端点
                ar[i][j] = ar[i - 1][j];//al记录翻转的左端点
                if(a[i] == b[j])
                {
                    dp[i][j] = dp[i - 1][j] + 1;
                    if(l == j && !al[i][j])//如果当前的j就是b开始翻转的左端点,更新记录
                        al[i][j] = i;
                    if(r == j)//当前的j是b翻转的右端点,记录更新
                        ar[i][j] = i;
                }
                if(dp[i][j - 1] > dp[i][j])//如果答案有更新就要更新答案
                {
                    dp[i][j] = dp[i][j - 1];
                    al[i][j] = al[i][j - 1];
                    ar[i][j] = ar[i][j - 1];
                }
            }
        }
        return dp[n][cnt];
    }
     
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d%s", &n, s + 1);
            for(int i = 1; i <= n; i++)
                a[i] = s[i] - '0';
            cnt = 0;
            for(int i = 0; i <= 9; i++)
                b[++cnt] = i;
            ansl = ansr = l = r = 1;
            ans = solve();
            for(int i = 0; i <= 9; i++) //枚举翻转b数组的每一段
            {
                for(int j = i + 1; j <= 9; j++)
                {
                    cnt = 0;
                    for(int k = 0; k <= i; k++)
                        b[++cnt] = k;
                    l = cnt+1;//左端点
                    for(int k = j; k >= i; k--)//只翻转i~j区间的数
                        b[++cnt] = k;
                    r = cnt;//右端点
                    for(int k = j; k <= 9; k++)
                        b[++cnt] = k;
                   /* for(int i=1; i<=cnt; i++)
                        printf("%d ",b[i]);
                    printf("
    ");*/
                    int tmp = solve();
                    if(ans < tmp && al[n][cnt] && ar[n][cnt])//不断更新答案
                    {
                        ans = tmp;
                        ansl = al[n][cnt], ansr = ar[n][cnt];
                    }
                }
            }
            printf("%d %d %d
    ", ans, ansl, ansr);
        }
        return 0;
    }
  • 相关阅读:
    Java开发常用知识点总结
    Net实现阿里云开放云存储服务(OSS)
    KEIL MDK-ARM Version 5.26正式版开发工具下载
    【NXP开发板应用—智能插排】4. PWM驱动
    【NXP开发板应用—智能插排】3.驱动GPIO点亮外接LED
    【NXP开发板应用—智能插排】2.初步解析example之GPI
    【NXP开发板应用—智能插排】1.如何使用scp传输文件
    Keil MDK最新版 5.25介绍及下载地址
    springmvc框架helloword
    单例设计模式
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10339365.html
Copyright © 2011-2022 走看看