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();
}
}