C. Playing Piano 动态规划

题目意思是给你一个n长度的数字串为a,让你构造一个n长度的数字串b值都为1-5满足以下条件:

正常的dfs暴力构造会超时,我试过了。。

可以开一个二维数组dp[i][j]用来表示b的第i个数字为j是否可行,标记为1或0;

因为第i个数字的大小只会影响第i+1个数字,每次确定i都根据第i-1的数字来判断。

再开一个二维数组pre[i][j]用来表示b的第i个 数字为j时的前一个数字是多少,最后倒推时用stack记录一下输出答案;

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int dp[maxn][6];
int pre[maxn][6];
stack<int> s;
int main()
{
    int n;
    scanf("%d", &n);
    for(int i=1; i<=n; i++)
        scanf("%d", &a[i]);
    for(int i=1; i<=5; i++)
        dp[1][i]=1;
    for(int i=2; i<=n; i++)
        for(int j=1; j<=5; j++)
        {
            if(dp[i-1][j]==0)
                continue;
            if(a[i]>a[i-1])
            {
                for(int k=j+1; k<=5; k++)
                {
                    dp[i][k]=1;
                    pre[i][k]=j;
                }
            }
            if(a[i]<a[i-1])
            {
                for(int k=j-1; k>=1; k--)
                {
                    dp[i][k]=1;
                    pre[i][k]=j;
                }
            }
            if(a[i]==a[i-1])
            {
                for(int k=1; k<=5; k++)
                    if(k!=j)
                    {
                        dp[i][k]=1;
                        pre[i][k]=j;
                    }
            }
        }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=5; j++)
            printf("%d ", pre[i][j]);
        printf("\n");
    }
    int t=0;
    for(int j=1; j<=5; j++)
    {
        if(dp[n][j]==1)
            t=j;
    }
    if(t==0)
    {
        printf("-1");return 0;
    }
    for(int i=n; i>=1; i--)
    {
        s.push(t);
        t=pre[i][t];
    }
    while(!s.empty())
    {
        printf("%d ", s.top());
        s.pop();
    }
}

猜你喜欢

转载自www.cnblogs.com/dongdong25800/p/9998980.html