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

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

->对于一摞煎饼可以选择其中的一个使得当前煎饼和之上的所有煎饼上下翻转,例如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[n]))
    {
        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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值