uva 120 Stacks of Flapjacks 策略,模拟,思路

本文介绍了一种名为煎饼排序的算法,通过一系列翻转操作使一组编号煎饼按大小顺序排列。具体步骤包括找到最大煎饼并将其翻转至底部,逐步完成整个序列的排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给你一叠大小(这里用直径表征)的煎饼,它们的标号是最底层的煎饼为1号,最顶层的那张为n号,即由下向上递增,给出一种操作flip(i),代表将i号煎饼及在其以上的所有煎饼形成的这一小叠颠倒顺序,比如原来是1-3-2-4-5,颠倒后为5-4-2-3-1

现在给你一叠煎饼,要求你施加一组flip操作,最终使得这叠煎饼的大小是从上往下一次递增的。输出这个序列。

其实现在回头想来,它要求你给出一种稳妥的策略,这思路并不困难:既然要求你最终达到“递增”序,说明一旦这叠煎饼输入了,我们的目的序是可以确定的,既然是递增,我们不妨就先将最大的那块放到正确的位置(即最底层),再把次大的那块放到正确的位置,以此类推,一块块达到最终位置了,整个序列也就符合要求了。

具体实现就是,对于输入的序列,考虑到规模不大,我们可以sort,得到目的序,然后走一个循环,每次循环,我们选择当前序列里没有达到目标位置的煎饼中的最大的那个,假设它是k号,我们就施加flip(k),即将这个煎饼翻到顶,然后,根据sort之后的目的序,我们知道这块煎饼应该去哪个位置,比如说是p,我们就再施加flip(p),这样,这块煎饼就达到目的位置了

当然要注意,每次施加flip都有可能影响其他的煎饼,这是因为flip操作是对一个区间作倒序。。并不是单纯的交换两块煎饼的位置,因此在操作过程中要实时模拟flip操作,这个写起来也许可以很讨巧。。然而我是感觉我写的麻烦了。。不过倒是顺利ac了

还有一坑。。输出要先输出一下原序列。。

code:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<algorithm>
#include<cstdlib>
//#include<windows.h>

#define maxn 201314
#define inf 0x3f3f3f3f
#define LL long long

using namespace std;
const double PI=(acos(-1));
int q[200];
int p[200];
int r[200];//这三个数组用来存储原序列,目的序列,以及在模拟flip操作的时候做一个对映
int ans[500];//存放答案序列
int n;
int nmax;
int indexx=0;
int main()
{
    while(scanf("%d",&q[indexx])!=EOF)
    {
        indexx++;
        while(getchar()!='\n')
        {
            scanf("%d",&q[indexx++]);
        }
        n=indexx;
        //cout<<n<<endl;
        indexx=0;
        for(int i=0; i<n; i++)
        {
            if(i<n-1){
            printf("%d ",q[i]);
            }
            else printf("%d\n",q[i]);
            p[i]=q[i];
        }
        sort(q,q+n);
        int j=0;
        int tmp;
        do
        {
            tmp=-1;
            int tmpindex=-1;
            for(int i=0; i<n; i++)
            {
                if(p[i]>tmp&&p[i]!=q[i])
                {
                    tmp=p[i];
                    tmpindex=i;
                }//选择当前序列里没有达到目标位置的煎饼中的最大的那个
            }
            //cout<<tmp<<endl;
            if(tmp!=-1)//找到了
            {
                if(tmpindex!=0)
                {
                    ans[j++]=n-tmpindex;
                    for(int i=0; i<n; i++)
                    {
                        if(i<=tmpindex)
                        {
                            r[tmpindex-i]=p[i];
                        }
                        else
                        {
                            r[i]=p[i];
                        }
                    }
                    for(int i=0; i<n; i++)
                    {
                        p[i]=r[i];
                    }
                }
                for(int i=0; i<n; i++)
                {
                    if(q[i]==tmp)
                    {
                        ans[j++]=n-i;
                        for(int j=0; j<n; j++)
                        {
                            if(j<=i)
                            {
                                r[i-j]=p[j];
                            }
                            else
                            {
                                r[j]=p[j];
                            }
                        }
                        for(int j=0; j<n; j++)
                        {
                            p[j]=r[j];
                        }
                        break;
                    }
                }
            }
        }
        while(tmp!=-1);//循环跳出条件是这么设置的
        //cout<<j<<endl;
        for(int i=0; i<j; i++)
            printf("%d ",ans[i]);
        printf("0\n");
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值