这个问题是看算法精华版时候看见的,人家的算法看了很头大,自己写一遍后觉得清楚多了
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
/*
* 分油算法:一个桶中有 12 斤油,要求倒出 6 斤,可现在另外只有两个桶,分别可装 8 斤与 5 斤,请问应如何来倒?
* 补充:这里的 12,6,8,5 都是变量,应该可以自己设置,输出是每一次分油的步骤。
*
* bfs 广度优先搜索,把探索到的状态放在临时表里,看是否探索又回到了原来的位置。
*
*
*
*/
namespace zboSorting.test.CSDN
{
public class SeparateOil
{
private int targetOil { get ; set ; }
private List <bottle > bottleList = new List <bottle >();
private List <status > bottleTotalStatus = new List <status >();
private bottle bottle1 = new bottle () {currentOil = 12, volumn = 12};
private bottle bottle2 = new bottle () {currentOil = 0, volumn = 8};
private bottle bottle3 = new bottle () {currentOil = 0, volumn = 5};
public SeparateOil()
{
bottle [] bottleArray = {bottle1, bottle2, bottle3};
bottleList.AddRange(bottleArray);
this .targetOil = 6;
bottleTotalStatus.Add(new status () {oilIn12 = 12, oilIn5 = 0, oilIn8 = 0, inSearch = true });
}
public void run()
{
List <status > searchStatusList = bottleTotalStatus.FindAll(status => status.inSearch == true );
while (searchStatusList.Count > 0)
{
status fromStatus = searchStatusList[0];
ResetBottles(fromStatus);
List <bottle > possibleFromBottle = getPossibleFrom();
List <bottle > possibleToBottle = getPossibleTo();
foreach (bottle fromBottle in possibleFromBottle)
{
foreach (bottle toBottle in possibleToBottle)
{
if (fromBottle != toBottle)
{
dumpOil(fromBottle, toBottle, fromStatus);
ResetBottles(fromStatus);
}
}
}
fromStatus.inSearch = false ;
searchStatusList = bottleTotalStatus.FindAll(status => status.inSearch == true );
}
}
private void ResetBottles(status fromStatus)
{
this .bottle1.currentOil = fromStatus.oilIn12;
this .bottle2.currentOil = fromStatus.oilIn8;
this .bottle3.currentOil = fromStatus.oilIn5;
}
private void dumpOil(bottle fromBottle, bottle toBottle, status fromStatus)
{
int canDumpOil = fromBottle.currentOil < (toBottle.volumn - toBottle.currentOil)
? fromBottle.currentOil
: (toBottle.volumn - toBottle.currentOil);
fromBottle.currentOil = fromBottle.currentOil - canDumpOil;
toBottle.currentOil = toBottle.currentOil + canDumpOil;
status status = new status ()
{
fromStatus = fromStatus,
oilIn12 = bottle1.currentOil,
oilIn8 = bottle2.currentOil,
oilIn5 = bottle3.currentOil,
inSearch = true
};
if (
bottleTotalStatus.Find(
s => (s.oilIn12 == status.oilIn12 && s.oilIn5 == status.oilIn5 && s.oilIn8 == status.oilIn8)) ==
null )
{
if (status.oilIn12 == 6 || status.oilIn8 == 6)
{
Console .WriteLine("find 6" );
while (status != null )
{
Console .WriteLine("A:" + status.oilIn12 + "B:" + status.oilIn8 + "C:" + status.oilIn5);
status = status.fromStatus;
}
}
else
{
bottleTotalStatus.Add(status);
}
}
}
private List <bottle > getPossibleTo()
{
List <bottle > possibleTo = new List <bottle >();
foreach (bottle b in bottleList)
{
if (b.currentOil < b.volumn)
possibleTo.Add(b);
}
return possibleTo;
}
private List <bottle > getPossibleFrom()
{
List <bottle > possibleFrom = new List <bottle >();
foreach (bottle b in bottleList)
{
if (b.currentOil > 0)
possibleFrom.Add(b);
}
return possibleFrom;
}
internal class bottle
{
public int volumn { get ; set ; }
public int currentOil { get ; set ; }
}
internal class status
{
public int oilIn12 { get ; set ; }
public int oilIn8 { get ; set ; }
public int oilIn5 { get ; set ; }
public status fromStatus { get ; set ; }
public bool inSearch = false ;
}
}
}