hdu6357(日了皮皮虾的dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6357

思路:要找最长上升子序列,所以b序列是0123456789这样的,拿原序列和b序列匹配,让b序列中每个数的数量尽量多那么答案肯定较优,因为要翻转一个区间,直接翻转原序列情况较多,所以可以翻转b序列,情况只有45种,比如你选了(3,6),那么b序列就变成了012365436789,然后只要拿翻转后的b序列和原序列比较,选出能让b序列中的每个数字数量尽量多的情况就好了(相对位置不能改变)。至于翻转哪个区间,可以像背包选了那些物品一样,也就是差不多像是路径压缩。(讲道理,不会dp,菜的一批)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <unordered_map>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod unsigned(1<<30)
#define pb push_back
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
int n,dp[100008][18],a[100008],b[18],num,qw[100008][18],mi,ma;
string s;
int main()
{
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>s;
        ma=0,mi=10;
        FOR(i,1,n) a[i]=s[i-1]-'0',ma=max(ma,a[i]),mi=min(mi,a[i]);
        int ans=0,l=1,r=1;
        FOR(x,mi,ma)
        {
            FOR(y,x,ma)
            {
                num=0;
                FOR(i,mi,x) b[++num]=i;
                FOL(i,y,x)  b[++num]=i;
                FOR(i,y,ma) b[++num]=i;
                FOR(i,1,n)
                {
                    FOR(j,1,num)
                    {
                        dp[i][j]=dp[i-1][j];
                        qw[i][j]=0;
                        if(a[i]==b[j])
                        {
                            dp[i][j]++;
                            qw[i][j]=2;
                        }
                        if(dp[i][j]<dp[i][j-1])
                        {
                            qw[i][j]=1;
                            dp[i][j]=dp[i][j-1];
                        }
                    }
                }
                if(ans<dp[n][num])
                {
                    int i,j;
                    ans=dp[n][num];
                    i=n,j=num;
                    l=r=1;
                    bool flag=1;
                    while(i>=1&&j>1)
                    {
                        if(b[j]>=x+1&&qw[i][j]==2) l=i;
                        if(b[j]<y&&flag&&qw[i][j]==2) flag=0,r=i;
                        if(qw[i][j]==1) j--;
                        else i--;
                    }
                    if(x==y) l=r;
                }
            }
        }
        printf("%d %d %d\n",ans,l,r);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40858062/article/details/81482344
今日推荐