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


}

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架