zoukankan      html  css  js  c++  java
  • 编程之美之馅饼排序

    如何找到这个问题的最优解呢?

    每次都把当前最大的和上面的馅饼一起翻转,这样最多需要翻转2(n-1)次即可完成馅饼的翻转。

    如果馅饼中有好几个不同的部分已经相对有序,每次翻转时,把两个本来应该相邻的烙饼尽可能的换到一起。

    此问题本质上是对剪枝函数进行修改:设定上界和下届。

    代码如下:

    #ifndef XINBINGSORT_H_INCLUDED
    #define XINBINGSORT_H_INCLUDED
    
    #include<cassert>
    #include<stdio.h>
    //烙饼排序实现
    class CPrefixSorting
    {
    public:
        CPrefixSorting()
        {
            m_nCakeCnt=0;
            m_nMaxSwap=0;
        }
        ~CPrefixSorting()
        {
            if(m_CakeArray!=NULL)
            {
                delete m_CakeArray;
            }
            if(m_SwapArray!=NULL)
            {
                delete m_SwapArray;
            }
            if(m_ReverseCakeArray!=NULL)
            {
                delete m_ReverseCakeArray;
            }
            if(m_ReverseCakeArraySwap!=NULL)
            {
                delete m_ReverseCakeArraySwap;
            }
        }
        //计算烙饼翻转信息
        void Run(int* pCakeArray,int nCakeCnt)
        {
            Init(pCakeArray,nCakeCnt);
    
            m_nSearch=0;    //搜索次数设置为0
            Search(0);
        }
    
        //输出烙饼具体翻转次数
        void Output()
        {
            for(int i=0;i<m_nMaxSwap;i++)
            {
                printf("%d ",m_SwapArray[i]);    //输出交换结果数组的值
            }
            printf("
      |Search Times| :%d
    ",m_nSearch);
            printf("Total Swap times=%d
    ",m_nMaxSwap);
        }
    
    private:
        //初始化数组信息
        void Init(int* pCakeArray,int nCakeCnt)
        {
            assert(pCakeArray!=NULL);
            assert(nCakeCnt>0);
    
            m_nCakeCnt=nCakeCnt;    //用形参给实参赋值
    
            //初始化烙饼数组
            m_CakeArray=new int[m_nCakeCnt];    //动态申请内存
            assert(m_CakeArray!=NULL);
            for(int i=0;i<m_nCakeCnt;i++)
            {
                m_CakeArray[i]=pCakeArray[i];
            }
    
            //设置最多交换次数信息
            m_nMaxSwap=UpperBound(m_nCakeCnt);
    
    
            //初始化交换数组结果
            m_SwapArray=new int[m_nMaxSwap+1];
            assert(m_SwapArray!=NULL);
    
            //初始化中间交换结果信息
            m_ReverseCakeArray=new int[m_nCakeCnt];
            for(int i=0;i<m_nCakeCnt;i++)
            {
                m_ReverseCakeArray[i]=m_CakeArray[i];
            }
            m_ReverseCakeArraySwap=new int[m_nMaxSwap];
        }
    
        //寻找当前翻转的上界
        int UpperBound(int nCakeCnt)
        {
            return nCakeCnt*2;
        }
    
        //寻找当前翻转的下界
        int LowerBound(int* pCakeArray,int nCakeCnt)
        {
            int t,ret=0;
    
            //根据当前数组的排序信息情况来判断最少需要交换多少次
            for(int i=1;i<nCakeCnt;i++)
            {
                //判断位置相邻的两个烙饼,是否为尺寸上相邻的
                t=pCakeArray[i]-pCakeArray[i-1];
                if((t==1)||(t==-1))
                {
    
                }
                else
                {
                    ret++;
                }
            }
            return ret;
        }
    
        //排序主函数
        void Search(int step)
        {
            int i,nEstimate;
    
            m_nSearch++;
    
            //估算这次搜索需要的最少交换次数
            nEstimate=LowerBound(m_ReverseCakeArray,m_nCakeCnt);
            if(step+nEstimate>m_nMaxSwap)
                return;
    
            //如果已经排好序,即完成翻转,输出结果
            if(IsSorted(m_ReverseCakeArray,m_nCakeCnt))
            {
                if(step<m_nMaxSwap)
                {
                    m_nMaxSwap=step;
                    for(i=0;i<m_nMaxSwap;i++)
                        m_SwapArray[i]=m_ReverseCakeArraySwap[i];
                }
                return;
            }
    
            //递归进行翻转
            for(i=1;i<m_nCakeCnt;i++)
            {
                Reverse(0,i);
                m_ReverseCakeArraySwap[step]=i;
                Search(step+1);
                Reverse(0,i);
            }
        }
    
        bool IsSorted(int* pCakeArray,int nCakeCnt)
        {
            for(int i=1;i<nCakeCnt;i++)
            {
                if(pCakeArray[i-1]>pCakeArray[i])
                {
                    return false;
                }
            }
            return true;
        }
    
        //翻转烙饼信息
        void Reverse(int nBegin,int nEnd)
        {
            assert(nEnd>nBegin);
            int i,j,t;
    
            //翻转烙饼信息
            for(i=nBegin,j=nEnd;i<j;i++,j--)
            {
                t=m_ReverseCakeArray[i];
                m_ReverseCakeArray[i]=m_ReverseCakeArray[j];
                m_ReverseCakeArray[j]=t;
            }
        }
    private:
        int* m_CakeArray;   //烙饼信息数组
        int  m_nCakeCnt;     //烙饼个数
        int  m_nMaxSwap;     //最多交换次数,根据前面的推断,最多的交换次数为m_nCakeCnt*2
    
        int* m_SwapArray;    //交换结果数组
    
        int* m_ReverseCakeArray;         //当前翻转烙饼信息数组
        int* m_ReverseCakeArraySwap;     //当前翻转烙饼交换结果数组
        int  m_nSearch;                  //当前搜索次数信息
    };
    
    
    #endif // XINBINGSORT_H_INCLUDED
    
    
    #include <iostream>
    #include "XinbingSort.h"
    using namespace std;
    
    #define Cnt 10
    
    int main()
    {
        CPrefixSorting *cps=new CPrefixSorting;
        int p_CakeArray[Cnt]={3,2,1,6,5,4,9,8,7,0};
    
        cps->Run(p_CakeArray,Cnt);  //开始计算
        cps->Output();
        return 0;
    }
    
  • 相关阅读:
    JQ对JSON的增删改
    Debug编辑通过转Release找不到命名空间
    Codeforces Round #740(Div. 2)
    2021“MINIEYE杯”中国大学生算法设计超级联赛(10)
    2021“MINIEYE杯”中国大学生算法设计超级联赛(8)
    Codeforces Round #737 (Div. 2)
    2021“MINIEYE杯”中国大学生算法设计超级联赛(7)
    2021牛客暑期多校训练营8
    2021牛客暑期多校训练营7
    2021“MINIEYE杯”中国大学生算法设计超级联赛(6)
  • 原文地址:https://www.cnblogs.com/fistao/p/3219999.html
Copyright © 2011-2022 走看看