您的位置:首页 > 其它

UVa 120 Stacks of Flapjacks 摞煎饼 - 插入排序

2017-10-10 00:24 351 查看
题意是给定一摞煎饼,每个煎饼有权值,然后你需要通过一些操作使得煎饼从上到下按照权值从小到大排序。而对于操作的解释如下:

->对于一摞煎饼可以选择其中的一个使得当前煎饼和之上的所有煎饼上下翻转,例如1,2,4,3变为3,4,2,1。

输出:每次选择的煎饼编号,编号从上到下依次为n,n-1…

N.B. Special Judge

《lrj紫书》例8-1

思考插入排序的过程,每次维护前i个数为有序数列,插入第i+1个数,需要先搜索需要插入的位置,然后依次交换插入即可。

这里可以利用这个思想,维持最上部分为有序,然后每次插入之下不满足顺序的数。

1.首先将数翻上去

2.查询需要插入的位置区间翻转

3.再将此位置之上因为第2步本不应该翻转的区间翻转回去(判断:如果只有一个数不用翻)

4.整体为倒序,消除第1步翻转的影响将倒序序列整体翻转

(n<=30咋折腾都行真开心233)

注意应该意识到这是一个排序问题,应该联想到两次翻转挪动一个数的性质进行插入排序。

像插入排序这种思想很普遍,假定一个已知问题,然后插入后继状态更新到下一个已知问题,然后赋初值即可(大概就是数学归纳法的套路了)

(吐槽一下UVa真的慢得不能忍。。。输入格式也不忍直视。。。)

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;

int n=1;
int s[50],temp[50];

void inverse(int x)
{
for(int i=1;i<=x;i++)
temp[i]=s[i];
for(int i=1;i<=x;i++)
s[i]=temp[x-i+1];
}
int next(int x)
{
for(int i=x;i<n;i++)
if(s[i]>s[i+1])return i+1;
return n+1;
}
int main()
{
while(~scanf("%d",&s
))
{
while(getchar()==' ')
scanf("%d",&s[++n]);
for(int i=1;i<=n;i++)
printf("%d ",s[i]);
puts("");
int tmp=0;
while(true)
{
tmp=next(tmp);
if(tmp>n)break;
printf("%d ",n-tmp+1);
//将1...n的标号转化为题目的n,n-1...标号,下同
inverse(tmp);//步骤1

int pos;
for(pos=2;pos<=tmp&&s[pos]>s[1];pos++);
pos--;

if(pos-1>1)inverse(pos-1),printf("%d ",n-pos+2);//步骤3
inverse(tmp),printf("%d ",n-tmp+1);//步骤4
}
printf("0\n");
n=1;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: