【题目描述】
因为课堂无聊至极,因此小何和小周在课堂上玩起了恢复排列的游戏!
小周先在草稿纸上写下 1..𝑛(1≤𝑛≤1000)的一个排列 𝑝1,𝑝2,…,𝑝𝑛 然后告诉小何另一个序列 𝑞1,𝑞2,…,𝑞𝑛−1,对于每一个 𝑖i 满足 𝑞𝑖=𝑝𝑖+𝑝𝑖+1(1≤𝑖<𝑛)。
基于小周的信息,小何必须恢复满足序列 𝑞 的“字典序最小”的排列 𝑝。排列 𝑎 字典序小于排列 𝑏,如果对于某个 𝑘,对于所有 𝑖<𝑘 均有 𝑎𝑖=𝑏𝑖,且 𝑎𝑘<𝑏𝑘,换句话说,这两个排列到某个位置之前都相同,在这个位置上 𝑎 小于 𝑏。
【输入格式】
输入的第一行包含一个整数 𝑛。
第二行包含 𝑛−1 个空格分隔的整数:𝑞1,𝑞2,…,𝑞𝑛-1。
【输出格式】
输出一行,包含 𝑛 个空格分隔的整数 𝑝1,𝑝2,…,𝑝𝑛,若无法还原,输出-1。
【输入输出样例】
Input
6
5 6 8 5 8
Output
4 1 5 3 2 6
【题解】
这道题怎么做呢?
【题意理解】
q是1~n的排列,所以q中的元素各不相同,则都是1~n中一个数字。
枚举算法:枚举排列 p 的第一项,设为p[1]=x(1~n),则可根据q来推算后面的各项:
p[2] = q[1] - p[1]
p[3] = q[2] - p[2]
……
若推算到某一项p[i]=q[i]-p[i]时,p[i]在之前出现过(标记数组),则枚举的x不合适,继续枚举下一个x。
时间复杂度:O(n^2)
【Code】
#include<bits/stdc++.h>
using namespace std;
int n;
int q[1100],p[1111];
int flag[1111],f = 0;
int main(){
cin >> n;
for(int i = 1;i <= n - 1;i++){
cin >> q[i];
}
for(int i = 1;i <= n;i++){
memset(flag,0,sizeof(flag));
bool f1 = 1;
p[1] = i;
flag[p[1]] = 1;
for(int j = 2;j <= n;j++){
p[j] = q[j - 1] - p[j - 1];
if(flag[p[j]] == 1 || p[j] <= 0){
f1 = 0;
break;
}
flag[p[j]] = 1;
}
if(f1 == 1){
for(int j = 1;j <= n;j++){
cout << p[j] << " ";
}
f = 1;
}
if(f == 1) break;
}
if(f == 0) cout << -1;
return 0;
}