C. Playing Piano
题意
给你一个a数组,让你按照规则构造b数组
规则如下
如果
a
i
<
a
i
+
1
a_i<a_{i+1}
ai<ai+1那么
b
i
<
b
i
+
1
b_i<b_{i+1}
bi<bi+1
如果
a
i
>
a
i
+
1
a_i>a_{i+1}
ai>ai+1那么
b
i
>
b
i
+
1
b_i>b_{i+1}
bi>bi+1
如果
a
i
=
a
i
+
1
a_i=a_{i+1}
ai=ai+1那么
b
i
!
=
b
i
+
1
b_i!=b_{i+1}
bi!=bi+1
给出b数组或者输出-1表示b数组不存在。
做法
之
前
用
的
是
判
−
1
之
后
爆
搜
的
做
法
,
但
是
复
杂
度
得
不
到
保
证
之前用的是判-1之后爆搜的做法,但是复杂度得不到保证
之前用的是判−1之后爆搜的做法,但是复杂度得不到保证
最
后
用
d
p
做
了
这
道
题
,
d
p
[
i
]
[
j
]
表
示
第
i
个
数
放
j
是
否
能
使
前
i
个
数
字
合
法
最后用dp做了这道题,dp[i][j]表示第i个数放j是否能使前i个数字合法
最后用dp做了这道题,dp[i][j]表示第i个数放j是否能使前i个数字合法
记
录
一
下
每
个
状
态
是
否
可
达
,
之
后
从
最
后
一
位
往
前
每
个
位
置
选
一
个
合
法
的
就
可
以
了
。
记录一下每个状态是否可达,之后从最后一位往前每个位置选一个合法的就可以了。
记录一下每个状态是否可达,之后从最后一位往前每个位置选一个合法的就可以了。
代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
int dp[maxn][7];
int a[maxn];
int b[maxn];
vector<int> tmp;
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++)
{
if(a[i]>a[i-1])
{
for(int j=1;j<=5;j++)
{
for(int k=j-1;k>=1;k--)
{
if(dp[i-1][k]) dp[i][j]=1;
}
}
}
else if(a[i]<a[i-1])
{
for(int j=1;j<=5;j++)
{
for(int k=j+1;k<=5;k++)
{
if(dp[i-1][k]) dp[i][j]=1;
}
}
}
else
{
for(int j=1;j<=5;j++)
{
for(int k=1;k<=5;k++)
{
if(j!=k&&dp[i-1][k]) dp[i][j]=1;
}
}
}
}
int flag=0;
for(int i=1;i<=5;i++) tmp.push_back(i);
for(int i=n;i>=1;i--)
{
int ff=0;
for(int j=0;j<tmp.size();j++)
{
if(dp[i][tmp[j]])
{
ff=1;
b[i]=tmp[j];
break;
}
}
if(i==1) break;
tmp.clear();
if(a[i-1]<a[i])
{
for(int j=1;j<b[i];j++) tmp.push_back(j);
}
else if(a[i-1]>a[i])
{
for(int j=b[i]+1;j<=5;j++) tmp.push_back(j);
}
else
{
for(int j=1;j<=5;j++)
{
if(j!=b[i]) tmp.push_back(j);
}
}
if(ff==0)
{
flag=1;
break;
}
}
if(flag==1) printf("-1\n");
else for(int i=1;i<=n;i++) printf("%d ",b[i]);
return 0;
}