题意:输入一个1 ~ n (1≤n≤300) 的排列,用不超过 2n2 次操作把它变成升序。操作只有两种:交换前两个元素(操作1):把第一个元素移动到最后(操作2)。例如:输入排列为4,2,3,1,一个合法的操作序列为12122,具体操作是:4231->2431->4312->3412->4123->1234。(本段摘自《算法竞赛入门经典(第2版)》)。
关于题意以上表述有一些问题,题目要求的是从1,2,3,…,n的升序序列转化成题目所给的输入,其他的一样。
分析:
从升序转换成输入的序列不好做,因此倒过来处理,其中把第一个元素放到最后这种操作改成把最后一个元素放到第一个就好了。最后的只要把结果倒着输出就可以了。
代码:
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <set>
#include <string>
using namespace std;
const int maxn = 305;
int n, tmp;
int a[maxn];
string ans;
bool judge()
{
for (int i = 0; i < n; ++i)
if (a[i] != i + 1)
return false;
return true;
}
void change()
{
tmp = a[n - 1];
for (int i = n - 2; i >= 0; --i)
a[i + 1] = a[i];
a[0] = tmp;
}
int main()
{
while (~scanf("%d", &n), n)
{
ans = "";
for (int i = 0; i < n; ++i)
scanf("%d", &a[i]);
if (n == 1)
{
printf("\n");
continue;
}
while (!judge())
{
if (a[0] > a[1] && a[0] != n)
{
swap(a[0], a[1]);
ans += "1";
}
else
{
change();
ans += "2";
}
}
for (int i = ans.size() - 1; i >= 0; --i)
printf("%c", ans[i]);
printf("\n");
}
return 0;
}