C. Playing Piano(dfs)

Problem - C - Codeforces

小Paul想学弹钢琴。他已经有了一首想要开始演奏的旋律。为简单起见,他将这个旋律表示为键号序列a1,a2,…,an:数字越大,它就越靠近钢琴键盘的右侧。

Paul非常聪明,知道关键是正确地为他要演奏的音符分配手指。如果他选择不方便的指法,那么他将浪费很多时间尝试学习如何用这些手指演奏旋律,他可能不会成功。

我们用数字1到5来表示手指。我们称任何手指数字序列b1,…,bn为指法。如果对于所有1≤i≤n−1,以下条件成立,则指法很方便:

如果ai<ai+1,则bi<bi+1,因为否则Paul需要从键盘上拿下手来演奏(i+1)次音符; 如果ai>ai+1,则bi>bi+1,原因相同; 如果ai=ai+1,则bi≠bi+1,因为连续使用同一个手指是愚蠢的,请注意bi和bi+1之间有≠而不是=。

请提供任何方便的指法,或者发现没有。

输入 第一行包含一个整数n(1≤n≤105),表示音符数量。

第二行包含n个整数a1,a2,…,an(1≤ai≤2⋅105),表示键盘上的音符位置。

输出 如果没有方便的指法,请打印-1。否则,打印n个数字b1,b2,…,bn,每个数字从1到5,用空格分隔,表示便利的指法。

Examples

input

Copy

5
1 1 4 2 2

output

Copy

1 4 5 4 5 

input

Copy

7
1 5 7 8 10 3 1

output

Copy

1 2 3 4 5 4 3 

input

Copy

19
3 3 7 9 8 8 8 8 7 7 7 7 5 3 3 3 3 8 8

output

Copy

1 3 4 5 4 5 4 5 4 5 4 5 4 3 5 4 3 5 4 

题解:
遇到这种限制比较多的构造,且用于构造的数比较小,那我们可以直接进行dfs来求答案,注意所给的限制条件全都要用上

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
int mod = 1e9 + 7;
int a[100050];
int n;
int vis[100050][11];
int num[100050];
int dfs(int x)
{
	if(x == n)
	return 1;
	for(int i = 1;i <= 5;i++)
	{
		if(!vis[x + 1][i])
		{
			if((a[x] == a[x + 1]&&num[x] != i)||(a[x] > a[x + 1]&&num[x] > i)||(a[x] < a[x + 1]&&num[x] < i))
			{
				num[x + 1] = i;
				vis[x + 1][i] = 1;
				if(dfs(x + 1))
				return 1;
//				dfs(x + 1);
//				vis[x + 1][i] = 0;
			}
		}
	}
	return 0;
}
void solve()
{
	cin >> n;
	for(int i = 1;i <= n;i++)
	{
		cin >> a[i];
	}
	int f = 0;
	for(int i = 1;i <= 5;i++)
	{
		num[1] = i;
		if(dfs(1))
		{
			f = 1;
			break;
		}
	} 
	if(f)
	{
		for(int i = 1;i <= n;i++)
		cout << num[i] <<" ";
	}
	else
	{
		cout <<"-1";
	} 
}
signed main()
{
//	ios::sync_with_stdio(0 );
//	cin.tie(0);cout.tie(0);
	int t = 1;
//	cin >> t;
	while(t--)
	{
		solve(); 
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值