您的位置:首页 > 其它

第1章 游戏之乐——一摞烙饼的排序

2015-06-25 17:02 281 查看

一摞烙饼的排序

  问题:写出一个程序,对于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("\n|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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: