zoukankan      html  css  js  c++  java
  • 第1章 游戏之乐——一摞烙饼的排序

    一摞烙饼的排序

      问题:写出一个程序,对于n块大小不一的烙饼,输出最优化的翻饼过程?要保证烙饼按照大小次序摆好——小的在上面,大的在下面。

    分析与解法:

    用java实现的代码如下:

    package chapter1youxizhilePrefixSorting;
    
    import java.util.Scanner;
    /**
     * 一摞烙饼的
     * @author DELL
     *
     */
    public class PrefixSorting {
        private int[] m_CakeArray;  //烙饼信息数组
        private int m_nCakeCnt;  //烙饼个数
        private int m_nMaxSwap;  //最多交换次数,根据推断,最多为(m_nCakeCnt-1)*2;
        private int[] m_SwapArray;  //交换结果数组
        private int[] m_ReverseCakeArray;    //当前翻转烙饼信息数组
        private int[] m_ReverseCakeArraySwap;  //当前翻转烙饼交换结果数组
        private int m_nSearch;    //当前搜索次数信息
        
        public PrefixSorting(int[] pCakeArray, int nCakeCnt){
            m_nCakeCnt = 0;
            m_nMaxSwap = 0;
            Run(pCakeArray, nCakeCnt);
        }
        
        /**
         * 计算烙饼翻转信息
         * @param pCakeArray  存储烙饼索引数组
         * @param nCakeCnt      烙饼个数
         */
        public void Run(int[] pCakeArray, int nCakeCnt){
            Init(pCakeArray, nCakeCnt);
            m_nSearch = 0;
            Search(0);
        }
        
        //输出烙饼具体翻转次数
        public void Output(){
            System.out.print("交换结果数组为:");
            for(int i=0;i<m_nMaxSwap;i++){
                System.out.print(m_SwapArray[i]+" ");
            }
            System.out.println("
    |Search Times| : "+ m_nSearch);
            System.out.println("Total Swap times = "+ m_nMaxSwap);
        }
        
        /**
         * 初始化数组信息
         * @param pCakeArray    存储烙饼索引数组
         * @param nCakeCnt    烙饼个数
         */
        private void Init(int[] pCakeArray, int nCakeCnt){
            if(pCakeArray==null)
                System.out.println("烙饼索引数组为空!");
            if(nCakeCnt <= 0)
                System.out.println("烙饼个数非法!");
            m_nCakeCnt = nCakeCnt;
            //初始化烙饼数组
            m_CakeArray = new int[m_nCakeCnt];
            for(int i=0;i<m_nCakeCnt;i++){
                m_CakeArray[i] = pCakeArray[i];
            }
            //设置最多交换次数信息
            m_nMaxSwap = UpBound(m_nCakeCnt);
            //初始化交换结果数组
            m_SwapArray = new int[m_nMaxSwap];
            //初始化中间交换结果信息
            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];
            
        }
        
        /**
         * 寻找当前翻转的上界
         * @param nCakeCnt 烙饼个数
         * @return
         */
        private int UpBound(int nCakeCnt){
            return (nCakeCnt-1)*2;
        }
        
        /**
         * 寻找当前翻转的下界
         * @param pCakeArray 当前翻转烙饼信息数组
         * @param nCakeCnt    当前烙饼数量
         * @return
         */
        private int LowerBound(int[] pCakeArray, int nCakeCnt){
            int t, ret = 0;
            //根据当前数组的排序信息情况来判断最少需要交换多少次
            for(int i=1;i<nCakeCnt;i++){
                //判断位置相邻的两个烙饼,是否为尺寸排序上相邻的
                t = pCakeArray[i] - pCakeArray[i-1];
                if(Math.abs(t)==1){
                    //尺寸排序上相邻不计数
                }else{
                    ret++;
                }
            }
            return ret;
        }
        
        //排序的主函数
        private 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++){
                Revert(0,i);
                if(step<m_nMaxSwap)
                    m_ReverseCakeArraySwap[step] = i;
                Search(step+1);
                Revert(0,i);
            }
        }
        
        /**
         * 判断是否排好序
         * @param pCakeArray 当前翻转烙饼信息数组
         * @param nCakeCnt    烙饼数量
         * @return
         */
        private boolean IsSorted(int[] pCakeArray, int nCakeCnt){
            for(int i=1;i<nCakeCnt;i++){
                if(pCakeArray[i-1] > pCakeArray[i]){
                    return false;
                }
            }
            return true;
        }
        
        /**
         * 翻转烙饼信息
         * @param nBegin 开始位置
         * @param nEnd 结束位置
         */
        private void Revert(int nBegin, int nEnd){
            if(nBegin>=nEnd){
                System.out.println("参数信息有误!开始位置不能大于等于结束位置!");
            }
            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;
            }
        }
        
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.println("请输入烙饼从上到下的半径,以逗号分隔:");
            String s = input.nextLine();
            String[] ch = s.split(",");
    //        int nCakeCnt = 10;
            int nCakeCnt = ch.length;
            int[] pCakeArray = new int[nCakeCnt];
            for(int i=0;i<nCakeCnt;i++){
                pCakeArray[i] = Integer.parseInt(ch[i]);
            }
    //        int[] pCakeArray = {3,2,1,6,5,4,9,8,7,0};
            PrefixSorting ps = new PrefixSorting(pCakeArray, nCakeCnt);
            ps.Output();
    
        }
    
    }

    程序运行结果如下:

    请输入烙饼从上到下的半径,以逗号分隔:
    3,2,1,6,5,4,9,8,7,0
    交换结果数组为:4 8 6 8 4 9 
    |Search Times| : 148015
    Total Swap times = 6
  • 相关阅读:
    基于sshpass批量实现主机间的key验证脚本
    一键安装mysql5.7.30脚本
    centos8网卡名称修改
    mysql分库备份脚本
    centos一键二进制编译安装mariadb-10.2.31脚本
    chrony时间同步服务简介及配置
    linux基于key验证
    expect 脚本语言中交互处理常用命令
    shell中数值测试和算术表达式比较
    JAVA Math的简单运用
  • 原文地址:https://www.cnblogs.com/gaopeng527/p/4600372.html
Copyright © 2011-2022 走看看