博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
任意次序的n个烙饼最小反转次数求解
阅读量:7031 次
发布时间:2019-06-28

本文共 4549 字,大约阅读时间需要 15 分钟。

 贴上详细的题目:

       星期五的晚上,一帮微软技术员在希格玛附近的“硬盘酒吧”谈算法问题。有个同事说:   我以前在烙饼店打工,顾客经常端非常多的烙饼。店里的饼大小不一, 我习惯在到达顾客饭桌前,把一摞饼按照大小次序摆好——小的在上面,大的在下面。由于我一只手托着盘子,只好用另一只手,一次抓住最上面的几块饼,把它们 上下颠倒个个儿,反复几次之后,这摞烙饼就排好序了。 

       假设有n块大小不一的烙饼,那最多/最少要翻几次,才能达到最后大小有序的结果呢? 吧台的酒保说:这太难了吧。我有个简单的问题。有一次我烙了三个饼,一个两面都焦了,一
个两面都是金黄色,一个一面是焦的,一面是金黄色,我把它们摞一起,只能看到最上面一个饼的一面,发现是焦的,问最上面这个饼的另一面是焦的概率是多少? 不少喝酒的人脱口而出:1/2! 上面的说法对吗?你能否写出一个程序,对于n块大小不一的烙饼,输出最优化的翻饼过程呢? 
  

 

ExpandedBlockStart.gif
ContractedBlock.gifusings
namespace CakeSorting
ExpandedBlockStart.gif
{
    
class Program
ExpandedSubBlockStart.gif    
{
ContractedSubBlock.gif        
Vars
        
static void Main(string[] args)
ExpandedSubBlockStart.gif        
{
            Program p 
= new Program();
            p.run();
        }
        
void run()
ExpandedSubBlockStart.gif        
{
            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()
ExpandedSubBlockStart.gif        
{
            
//初始化赋值
            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++)
ExpandedSubBlockStart.gif            
{
                cakeSizeArray[i] 
= i;
            }
//大饼直径初始化
            
foreach (int i in cakeSizeArray)
ExpandedSubBlockStart.gif            
{
                cakes.Enqueue(i);
            }
//大饼队列化
        }
        
void enumeratQueue(int cn)
ExpandedSubBlockStart.gif        
{
            
if (cn == 1)
ExpandedSubBlockStart.gif            
{
                
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++)
ExpandedSubBlockStart.gif            
{
                
int t = cakes.Dequeue();
                cakeArray[cn 
- 1= t;
                enumeratQueue(cn 
- 1);
                cakes.Enqueue(t);
            }
        }
        
void search(int step)
ExpandedSubBlockStart.gif        
{
            
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++)
ExpandedSubBlockStart.gif            
{
                
if (i == cakeArray.Length - 1)
ExpandedSubBlockStart.gif                
{
                    maxTime 
= step;
                    
return;
                }
            }
//排序成功退出
            
for (int i = 0; i < cakeArray.Length; i++)
ExpandedSubBlockStart.gif            
{
                revert(
0, i);
                search(step
+1);
                revert(
0, i);
            }
//递归穷举所有方案
        }
        
void revert(int begin, int end)
ExpandedSubBlockStart.gif        
{
            
int t = cakeArray[begin];
            
for (int i = begin, j = end; i < j; i++, j--)
ExpandedSubBlockStart.gif            
{
                t 
= cakeArray[i];
                cakeArray[i] 
= cakeArray[j];
                cakeArray[j] 
= t;
            }
        }
        
void show()
ExpandedSubBlockStart.gif        
{
            
foreach (int i in cakeArray)
ExpandedSubBlockStart.gif            
{
                Console.Write(
"{0}\t", i);
            }
            Console.Write(
"\nMaxTime is:{0}\tMinTime is:{1}\n**************************************************\n",maxTime ,minTime);
        }
        
void setMaxTime()
ExpandedSubBlockStart.gif        
{
            
//maxTime = 2 * (cakeNum - 1);
            maxTime = (5 * cakeNum + 5/ 3 < 2 * (cakeNum - 1? (5 * cakeNum + 5/ 3 : 2 * (cakeNum - 1);
        }
        
int getLowerTime()
ExpandedSubBlockStart.gif        
{
            
int count=0;
            
for (int i = 1; i < cakeNum; i++)
ExpandedSubBlockStart.gif            
{
                
if (Math.Abs(cakeArray[i - 1- cakeArray[i]) != 1)
                    count
++;
            }
            
return count;
        }
    }
}

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

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

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

c#代码:

 

ExpandedBlockStart.gif
ContractedBlock.gifusings
namespace CakeSorting
ExpandedBlockStart.gif
{
    
class Program
ExpandedSubBlockStart.gif    
{
        
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)
ExpandedSubBlockStart.gif        
{
            Program p 
= new Program();
            p.run();
        }
        
void run()
ExpandedSubBlockStart.gif        
{
            init();
            enumeratQueue(cakes.Count());
            Console.ReadLine();
        }
        
void init()
ExpandedSubBlockStart.gif        
{
            
//初始化赋值
            setMaxTime();
            minTime 
= 0;
            cakeArray 
= new int[cakeNum];
            cakeSizeArray 
= new int[cakeNum];
            cakes 
= new Queue<int>();
            
for (int i = 0; i < cakeSizeArray.Length; i++)
ExpandedSubBlockStart.gif            
{
                cakeSizeArray[i] 
= i;
            }
//大饼直径初始化
            
foreach (int i in cakeSizeArray)
ExpandedSubBlockStart.gif            
{
                cakes.Enqueue(i);
            }
//大饼队列化
        }
        
void enumeratQueue(int cn)
ExpandedSubBlockStart.gif        
{
            
if (cn == 1)
ExpandedSubBlockStart.gif            
{
                
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++)
ExpandedSubBlockStart.gif            
{
                
int t = cakes.Dequeue();
                cakeArray[cn 
- 1= t;
                enumeratQueue(cn 
- 1);
                cakes.Enqueue(t);
            }
        }
        
void search(int step)
ExpandedSubBlockStart.gif        
{
            
if (step > maxTime)
                
return;//大于2(n-1)时退出
            
for (int i = 1; cakeArray [i-1]<cakeArray [i]; i++)
ExpandedSubBlockStart.gif            
{
                
if (i == cakeArray.Length - 1)
ExpandedSubBlockStart.gif                
{
                    maxTime 
= step;
                    
return;
                }
            }
//排序成功退出
            
for (int i = 0; i < cakeArray.Length; i++)
ExpandedSubBlockStart.gif            
{
                revert(
0, i);
                search(step
+1);
                revert(
0, i);
            }
//递归穷举所有方案
        }
        
void revert(int begin, int end)
ExpandedSubBlockStart.gif        
{
            
int t = cakeArray[begin];
            
for (int i = begin, j = end; i < j; i++, j--)
ExpandedSubBlockStart.gif            
{
                t 
= cakeArray[i];
                cakeArray[i] 
= cakeArray[j];
                cakeArray[j] 
= t;
            }
        }
        
void show()
ExpandedSubBlockStart.gif        
{
            
foreach (int i in cakeArray)
ExpandedSubBlockStart.gif            
{
                Console.Write(
"{0}\t", i);
            }
            Console.Write(
"\nMaxTime is:{0}\tMinTime is:{1}\n",maxTime ,minTime);
        }
        
void setMaxTime()
ExpandedSubBlockStart.gif        
{
            maxTime 
= 2 * (cakeNum - 1);
        }
    }
}

 

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

运行结果: 

 

ExpandedBlockStart.gif
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CakeArraySorting
ExpandedBlockStart.gif
{
    
class Program
ExpandedSubBlockStart.gif    
{
ContractedSubBlock.gif        
Main
ContractedSubBlock.gif        
Parameters
ContractedSubBlock.gif        
Process
ContractedSubBlock.gif        
AppendMethods
    }
    
}

 

 

本文转自today4king博客园博客,原文链接:http://www.cnblogs.com/jinzhao/archive/2008/08/22/1274432.html,如需转载请自行联系原作者
你可能感兴趣的文章
红帽论坛北京站召开 设立亚太开放创新实验室
查看>>
苏宁11.11:如何基于异步化打造会员任务平台?
查看>>
区块链和数据科学:如果同时应用这两种技术,将会实现什么?
查看>>
Oracle即将发布的全新Java垃圾收集器 ZGC
查看>>
深入浅出Tensorflow(三):训练神经网络模型的常用方法
查看>>
Blazor将.NET带回到浏览器
查看>>
利用人工智能提升团队包容性
查看>>
详解分布式系统本质:“分治”和“冗余”
查看>>
gRPC-Web发布,REST又要被干掉了?
查看>>
全站爬虫项目一阶段总结
查看>>
在项目中引入领域驱动设计的经验
查看>>
用关系型NoSQL回到未来
查看>>
Jeff Bean谈Flink与流式处理的5大新发现
查看>>
技术寡头争霸传之:控制开源工具,就控制了整个生态
查看>>
微软把UWP定位成业务线应用程序开发平台
查看>>
2018腾讯云+未来峰会互联网专场:腾讯云智能物联解决方案亮相
查看>>
Python数据可视化的10种技能
查看>>
关于有效的性能调优的一些建议
查看>>
微软发起Java on Azure调查,呼吁Java社区积极参与
查看>>
搭建svn仓库
查看>>