当前位置: 代码迷 >> 综合 >> 【 Codeforces Round #522 C. Playing Piano】 DP+记录路径
  详细解决方案

【 Codeforces Round #522 C. Playing Piano】 DP+记录路径

热度:35   发布时间:2023-12-29 02:27:13.0

C. Playing Piano

题意

给你一个a数组,让你按照规则构造b数组
规则如下
如果ai&lt;ai+1a_i&lt;a_{i+1}ai?<ai+1?那么bi&lt;bi+1b_i&lt;b_{i+1}bi?<bi+1?
如果ai&gt;ai+1a_i&gt;a_{i+1}ai?>ai+1?那么bi&gt;bi+1b_i&gt;b_{i+1}bi?>bi+1?
如果ai=ai+1a_i=a_{i+1}ai?=ai+1?那么bi!=bi+1b_i!=b_{i+1}bi?!=bi+1?
给出b数组或者输出-1表示b数组不存在。

做法

之前用的是判?1之后爆搜的做法,但是复杂度得不到保证之前用的是判-1之后爆搜的做法,但是复杂度得不到保证?1
最后用dp做了这道题,dp[i][j]表示第i个数放j是否能使前i个数字合法最后用dp做了这道题,dp[i][j]表示第i个数放j是否能使前i个数字合法dp,dp[i][j]ij使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;
}
  相关解决方案