C. Playing Piano
题目链接:https://codeforces.com/contest/1079/problem/C
题意:
给出数列{an},现在要求你给出一个数列{bn},满足:
1.当an+1>an时,有bn+1>bn;2.当an+1=an时,有bn+1!=bn;3.当an+1<an时,有bn+1<bn。 且满足1<=bn<=5。
题解:
我们可以考虑动态规划,设dp(i,j)为第i位置时,b(i)=j是否可行。
那么状态转移时可以分ai>ai-1,ai=ai-1,ai<ai-1三种情况考虑,同时记录一下路径方便输出。
具体见代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5+5; int dp[N][10],path[N][10]; int n ; int a[N]; int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>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; path[i][k]=j; } }else if(a[i]<a[i-1]){ for(int k=1;k<j;k++){ dp[i][k]=1; path[i][k]=j; } }else{ for(int k=1;k<=5;k++){ if(k==j) continue ; dp[i][k]=1; path[i][k]=j; } } } } int ok = 0,j; for(int i=1;i<=5;i++) if(dp[n][i]) ok=1,j=i; if(!ok){ printf("-1"); return 0; } stack <int> s; for(int i=n;i!=0;i--){ s.push(j); j=path[i][j]; } while(!s.empty()){ cout<<s.top()<<" "; s.pop(); } return 0; }