贴上详细的题目:

星期五的晚上,一帮微软技术员在希格玛附近的“硬盘酒吧”谈算法问题。有个同事说:   我以前在烙饼店打工,顾客经常端非常多的烙饼。店里的饼大小不一, 我习惯在到达顾客饭桌前,把一摞饼按照大小次序摆好——小的在上面,大的在下面。由于我一只手托着盘子,只好用另一只手,一次抓住最上面的几块饼,把它们 上下颠倒个个儿,反复几次之后,这摞烙饼就排好序了。
       假设有n块大小不一的烙饼,那最多/最少要翻几次,才能达到最后大小有序的结果呢? 吧台的酒保说:这太难了吧。我有个简单的问题。有一次我烙了三个饼,一个两面都焦了,一
个两面都是金黄色,一个一面是焦的,一面是金黄色,我把它们摞一起,只能看到最上面一个饼的一面,发现是焦的,问最上面这个饼的另一面是焦的概率是多少? 不少喝酒的人脱口而出:1/2! 上面的说法对吗?你能否写出一个程序,对于n块大小不一的烙饼,输出最优化的翻饼过程呢?

Code
usings#region usings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
#endregion

namespace CakeSorting
{
    class Program
    {
        Vars#region Vars
        private int[] cakeSizeArray;//大饼直径队列
        private int[] cakeArray;//大饼队列
        private Stack<int> steps;
        private Queue<int> cakes;
        const int cakeNum = 7;
        private int maxTime = 0;
        private int minTime = 0;
        #endregion

        static void Main(string[] args)
        {
            Program p = new Program();
            p.run();
        }

        void run()
        {
            DateTime dt = DateTime.Now;
            TimeSpan ts;
            init();
            enumeratQueue(cakes.Count());
            ts = DateTime.Now - dt;
            Console.WriteLine("\nResult\nMinTime is:{0}\t{1}:{2}:{3}:{4}", minTime, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
            Console.ReadLine();
        }

        void init()
        {
            //初始化赋值

            setMaxTime();

            minTime = 0;

            cakeArray = new int[cakeNum];

            cakeSizeArray = new int[cakeNum];

            cakes = new Queue<int>();

            steps = new Stack<int>();

            for (int i = 0; i < cakeSizeArray.Length; i++)
            {
                cakeSizeArray[i] = i;
            }//大饼直径初始化

            foreach (int i in cakeSizeArray)
            {
                cakes.Enqueue(i);
            }//大饼队列化
        }

        void enumeratQueue(int cn)
        {
            if (cn == 1)
            {
                int t = cakes.Dequeue();
                cakeArray[0] = t;
                setMaxTime();
                search(0);
                minTime = maxTime > minTime ? maxTime : minTime;
                show();
                cakes.Enqueue(t);
            }

            for (int i = 0; i < cn; i++)
            {
                int t = cakes.Dequeue();
                cakeArray[cn - 1] = t;
                enumeratQueue(cn - 1);
                cakes.Enqueue(t);
            }
        }

        void search(int step)
        {
            if (maxTime < 15 * cakeNum / 14)
                return;//当此最优解必小于此最劣情况下界时剪枝

            if (step > maxTime)
                return;//大于2(n-1)时退出

            if (step + getLowerTime() > maxTime)
                return;//最优预计

            for (int i = 1; cakeArray [i-1]<cakeArray [i]; i++)
            {
                if (i == cakeArray.Length - 1)
                {
                    maxTime = step;
                    return;
                }
            }//排序成功退出

            for (int i = 0; i < cakeArray.Length; i++)
            {
                revert(0, i);
                search(step+1);
                revert(0, i);
            }//递归穷举所有方案
        }

        void revert(int begin, int end)
        {
            int t = cakeArray[begin];
            for (int i = begin, j = end; i < j; i++, j--)
            {
                t = cakeArray[i];
                cakeArray[i] = cakeArray[j];
                cakeArray[j] = t;
            }
        }

        void show()
        {
            foreach (int i in cakeArray)
            {
                Console.Write("{0}\t", i);
            }
            Console.Write("\nMaxTime is:{0}\tMinTime is:{1}\n**************************************************\n",maxTime ,minTime);
        }

        void setMaxTime()
        {
            //maxTime = 2 * (cakeNum - 1);
            maxTime = (5 * cakeNum + 5) / 3 < 2 * (cakeNum - 1) ? (5 * cakeNum + 5) / 3 : 2 * (cakeNum - 1);
        }

        int getLowerTime()
        {
            int count=0;
            for (int i = 1; i < cakeNum; i++)
            {
                if (Math.Abs(cakeArray[i - 1] - cakeArray[i]) != 1)
                    count++;
            }
            return count;
        }
    }
}

上一篇写了当已知一个烙饼队列,求出其最少反转次数。

这一篇中将求出如题即n个烙饼最坏情况下需要多少次反转。

《编程之美》中给出目前最优最大下界:15n/14,最小的上界(5n+5)/3。

c#代码:

Code
usings#region usings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
#endregion

namespace CakeSorting
{
    class Program
    {
        private int[] cakeSizeArray;//大饼直径队列
        private int[] cakeArray;//大饼队列
        private Queue<int> cakes;
        const int cakeNum = 6;
        private int maxTime = 0;
        private int minTime = 0;
        static void Main(string[] args)
        {
            Program p = new Program();
            p.run();
        }

        void run()
        {
            init();
            enumeratQueue(cakes.Count());
            Console.ReadLine();
        }

        void init()
        {
            //初始化赋值

            setMaxTime();

            minTime = 0;

            cakeArray = new int[cakeNum];

            cakeSizeArray = new int[cakeNum];

            cakes = new Queue<int>();

            for (int i = 0; i < cakeSizeArray.Length; i++)
            {
                cakeSizeArray[i] = i;
            }//大饼直径初始化

            foreach (int i in cakeSizeArray)
            {
                cakes.Enqueue(i);
            }//大饼队列化
        }

        void enumeratQueue(int cn)
        {
            if (cn == 1)
            {
                int t = cakes.Dequeue();
                cakeArray[0] = t;
                setMaxTime();
                search(0);
                minTime = maxTime > minTime ? maxTime : minTime;
                show();
                cakes.Enqueue(t);
            }

            for (int i = 0; i < cn; i++)
            {
                int t = cakes.Dequeue();
                cakeArray[cn - 1] = t;
                enumeratQueue(cn - 1);
                cakes.Enqueue(t);
            }
        }

        void search(int step)
        {
            if (step > maxTime)
                return;//大于2(n-1)时退出

            for (int i = 1; cakeArray [i-1]<cakeArray [i]; i++)
            {
                if (i == cakeArray.Length - 1)
                {
                    maxTime = step;
                    return;
                }
            }//排序成功退出

            for (int i = 0; i < cakeArray.Length; i++)
            {
                revert(0, i);
                search(step+1);
                revert(0, i);
            }//递归穷举所有方案
        }

        void revert(int begin, int end)
        {
            int t = cakeArray[begin];
            for (int i = begin, j = end; i < j; i++, j--)
            {
                t = cakeArray[i];
                cakeArray[i] = cakeArray[j];
                cakeArray[j] = t;
            }
        }

        void show()
        {
            foreach (int i in cakeArray)
            {
                Console.Write("{0}\t", i);
            }
            Console.Write("\nMaxTime is:{0}\tMinTime is:{1}\n",maxTime ,minTime);
        }

        void setMaxTime()
        {
            maxTime = 2 * (cakeNum - 1);
        }
    }
}

最优解(已经使用了书中说的当碰到相同状态时根据是否是是更优解的情况判断,程序还可以继续优化,有兴趣的朋友一起讨论):

运行结果:

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CakeArraySorting
{
    class Program
    {
        Main#region Main

        static void Main(string[] args)
        {
            Program p = new Program();
            p.run();
            Console.ReadLine();
        }

        #endregion

        Parameters#region Parameters
        
        private int[] cakeSizeArray;//大饼直径队列

        private int[] cakeArray;//大饼队列

        private int[] maxCakeArray;

        private Queue<int> cakes;

        const int cakeNum = 9;

        private int maxTime = 0;

        private int minTime = 0;

        private int lowwerTime;

        private int ID = 0;

        private int[] timeTable;

        private DateTime startTime;

        private TimeSpan ts;

        #endregion

        Process#region Process

        void run()
        {
            init();
            enumeratQueue(cakes.Count());
            ts = DateTime.Now - startTime;

            Console.Write("MaxCakeArray:\t");
            foreach (int i in maxCakeArray)
            {
                Console.Write("{0}\t", i);
            }
            Console.WriteLine("\nCost Time:{0}\t MaxTime:{1}", ts, minTime);
        }

        void init()
        {
            //初始化赋值
            startTime = DateTime.Now;

            setMaxTime();

            lowwerTime = (int)15 * cakeNum / 14;

            minTime = 0;

            cakeArray = new int[cakeNum];

            cakeSizeArray = new int[cakeNum];

            maxCakeArray = new int[cakeNum];

            cakes = new Queue<int>(cakeNum);

            setCakes();

            cakesEnqueue();

            timeTable = new int[getFactorial(cakeNum)];

        }

        #endregion

        AppendMethods#region AppendMethods

        void enumeratQueue(int cn)
        {
            if (cn == 1)
            {
                int t = cakes.Dequeue();
                cakeArray[0] = t;
                setMaxTime();
                Console.Write("ID:{0}", ID);
                //foreach (int i in cakeArray)
                //{
                //    Console.Write("\t{0}", i);
                //}
                if (getNeberNum() == cakeNum - 1)//无相邻直径大小的饼
                {
                    setTimeTable();
                    search(0);
                    minTime = maxTime > minTime ? maxTime : minTime;
                    if (minTime == maxTime)
                        Array.Copy(cakeArray, maxCakeArray, cakeNum);
                    //show();
                }
                else
                {
                    Console.WriteLine("jump!.");
                }
                ID++;
                cakes.Enqueue(t);
            }

            for (int i = 0; i < cn; i++)
            {
                int t = cakes.Dequeue();
                cakeArray[cn - 1] = t;
                enumeratQueue(cn - 1);
                cakes.Enqueue(t);
            }
        }

        void search(int step)
        {
            //if (cakeNum == 1)
            //    return;

            if (step > maxTime)
                return;//大于2(n-1)时退出

            if (step + getNeberNum() > maxTime)
                return;

            int p = getID();
            if (step <= timeTable[p])
            {
                timeTable[p] = step;
            }
            else
                return;

            for (int i = 1; cakeArray[i - 1] < cakeArray[i]; i++)
            {
                if (i == cakeArray.Length - 1)
                {
                    maxTime = step;
                    return;
                }
            }//排序成功退出

            for (int i = 0; i < cakeArray.Length; i++)
            {
                revert(0, i);
                search(step+1);
                revert(0, i);
            }//递归穷举所有方案
        }

        void revert(int begin, int end)
        {
            int t = cakeArray[begin];
            for (int i = begin, j = end; i < j; i++, j--)
            {
                t = cakeArray[i];
                cakeArray[i] = cakeArray[j];
                cakeArray[j] = t;
            }
        }

        void show()
        {
            Console.Write("\nMaxTime is:{0}\tMinTime is:{1}\n",maxTime ,minTime);
        }

        void setCakes()
        {
            for (int i = 0; i < cakeSizeArray.Length; i++)
            {
                cakeSizeArray[i] = i;
            }//大饼直径初始化,简便期间直接用相邻数字
        }

        void cakesEnqueue()
        {
            foreach (int i in cakeSizeArray)
            {
                cakes.Enqueue(i);
            }//大饼队列化
        }

        void setMaxTime()
        {
            //maxTime = 2 * (cakeNum - 1);
            maxTime = (5 * cakeNum + 5) / 3;
        }

        int getNeberNum()
        {
            int ret = 0;
            for (int i = 1; i < cakeNum;i++ )
            {
                if (Math.Abs(cakeArray[i - 1] - cakeArray[i]) != 1)
                {
                    ret++;
                }
            }
            return ret;
        }

        int getMaxLowwerNum()//计算15n/14~=n的最大数,计算得为14
        {
            int i = 1;
            for (; 15 * i / 14 - i < 1; i++) ;
                return i;
        }

        int getFactorial(int n)
        {
            int ret;
            for (ret = n; n > 1; n--)
                ret *= n - 1;
            return ret;
        }

        int getID( )
        {
            int ret = 0;
            for (int i = 0; i < cakeArray.Length; i++)
            {
                ret += getNumSize(i) * getFactorial(cakeNum - i - 1);
            }
            return ret;
        }

        int getNumSize(int p)
        {
            int ret=0;
            for (int i = p + 1; i < cakeArray.Length; i++)
            {
                if (cakeArray[p] < cakeArray[i])
                    ret++;
            }
            return ret;
        }

        void setTimeTable()
        {
            for (int i = 0; i < timeTable.Length; i++)
            {
                timeTable[i] = (int)(5 * cakeNum + 5) / 3;
            }
        }

        #endregion
    }


    
}

转载于:https://www.cnblogs.com/jinzhao/archive/2008/08/22/1274432.html

任意次序的n个烙饼最小反转次数求解 暑期学习笔记(十)相关推荐

  1. linux最小系统 安装教程,Linux 学习笔记 1 使用最小的系统,从分区安装系统开始,...

    Linux 学习笔记 1 使用最小的系统,从分区安装系统开始, 我们常用的linux系统在安装过程中大多都省略了对系统进行分区的操作,以至于后期,不了解什么是分区以及分区当中最基本的一些概念, 我们不 ...

  2. LeetCode——1888. 使二进制字符串字符交替的最少反转次数(Minimum Number of Flips to Make the Binary ...)[中等]——分析及代码(Java)

    LeetCode--1888. 使二进制字符串字符交替的最少反转次数[Minimum Number of Flips to Make the Binary String Alternating][中等 ...

  3. 算法--运算的最小翻转次数

    题目 给你三个正整数 a.b 和 c.你可以对 a 和 b 的二进制表示进行位翻转操作,返回能够使按位或运算 a OR b == c 成立的最小翻转次数.「位翻转操作」是指将一个数的二进制表示任何单个 ...

  4. 995. K 连续位的最小翻转次数

    链接:995. K 连续位的最小翻转次数 题解: https://leetcode-cn.com/problems/minimum-number-of-k-consecutive-bit-flips/ ...

  5. python半径为3圆形区域边界曲线_OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓...

    本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ...

  6. ESL3.4 学习笔记(奇异值分解与拉格朗日乘子法下的岭回归,Lasso回归,最小角回归及三者对比分析)

    3.4 收缩的方法 这是一篇有关<统计学习基础>,原书名The Elements of Statistical Learning的学习笔记,该书学习难度较高,有很棒的学者将其翻译成中文并放 ...

  7. LeetCode简单题之最小操作次数使数组元素相等

    题目 给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 .返回让数组所有元素相等的最小操作次数. 示例 1: 输入:nums = [1,2,3] 输出:3 解释: 只需要3次 ...

  8. 一道题,最小操作次数使数组元素相等引发的思考

    前言 最近在打卡力扣刷题,一道简单题但是感觉挺好的. 力扣453:最小操作数使数组相等. 题目描述为: 给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 .返回让数组所有元素 ...

  9. 每天一道LeetCode-----将字符串切分,使每个子串都是回文串,计算所有可能结果和最小切分次数

    Palindrome Partitioning 原题链接Palindrome Partitioning 对字符串进行切分,使得切分出的每个子串都是回文串,返回所有的切分可能 对于每个字符都可能在它的位 ...

最新文章

  1. 龙岩学院计算机二级报名时间,福建龙岩学院2015年12月计算机等级考试报名通知...
  2. JZOJ 5405. 【NOIP2017提高A组模拟10.10】Permutation
  3. debug内exe文件复制到桌面无法打开_Qt打包生成exe步骤和无法定位程序输入点_gxx_personality_v0于动态链接库...
  4. obfuscator-llvm Theos 集成配置
  5. SpringToolsSuite (STS)或Eclipse安装gradle
  6. 4代hiv检测50元_别瞧不起国货!这4个姥姥辈的护肤品,真心好用,还不到50元
  7. CVPR 2022 论文和开源项目合集
  8. 已解决:手动打包war包结果无法在Tomcat中部署
  9. JS函数表达式的特征和递归
  10. Oracle merge into 使用记录
  11. soapui使用教程2-属性与脚本
  12. 电脑网络里显示有两台计算机,2台电脑能共用一个显示器吗
  13. 2020年“华为杯”中国研究生数学建模竞赛题目及简单分析
  14. VBM法MRI图像处理——记第一次使用cat12
  15. android 水滴动画效果图,Android控件实现水滴效果
  16. 2018年天津大学夏令营机试第一题
  17. 虚拟偶像 “造星” 指南,二次元、超写实、智能驱动,你会粉上谁?
  18. 51nod:1079 中国剩余定理(数学)
  19. CSDN如何上传视频
  20. Fluent报错cl-set-default-save-dir: path does not exist.

热门文章

  1. python数据类型详解
  2. Ubuntu 下配置 SSH服务全过程及问题解决
  3. myeclipse 10创建maven项目
  4. FreeMarker中文帮助手册API文档,基础入门学习文档
  5. 【Oracle】查找每期数据都存在的产品
  6. 替换Android自带apk【转】
  7. wdcp3.2.6版 https全站跳转 标记待细化
  8. C++实现动态顺序表
  9. PHP date 格式化一个本地时间/日期
  10. 【转载】浅谈缺陷截图处理