分油算法:一个桶中有12斤油,要求倒出6斤,可现在另外只有两个桶,分别可装8斤与5斤,请问应如何来倒?
补充:这里的12,6,8,5都是变量,应该可以自己设置,输出是每一次分油的步骤.
其实也就一个广度搜索(BFS)。
从初始状态(12,0,0)到最终有某一个数是6就行了。
3个桶A、B、C,关系只有6种,A->B(A倒入B),B->C,c->A还有反过来倒。
从某个状态扩展出6个新的状态直至达到目标状态。
为了避免重复搜索,可以加个3维数组state[i][j][k]用以表示状态(i,j,k)已经出现,不用对它进行扩展(程序中表现为不入队)。
#include "stdafx.h"
#include <iostream>
#include <cstring> // for memset and memcmp
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define HASH(s) hash[s.vol[0]][s.vol[1]][s.vol[2]]
struct state
{
int vol[3];
int depth;
int parent;
};
//瓶子的容量
const int capacity[3] = {12, 8, 5};
const int QUEUE_SIZE = 100000;
state queue[QUEUE_SIZE]; // for bfs
void print_answer(int k)
{
int stack[100];
int p = 0;
int j;
while (k != -1)
{
stack[p++] = k;
k = queue[k].parent;
}
while (p--)
{
std::cout << "Step " << queue[stack[p]].depth << ":/t";
for (j=0; j <3; j++)
{
std::cout << queue[stack[p]].vol[j] << '/t';
}
std::cout << std::endl;
}
}
int main(void)
{
static short int hash[100][100][100]; // for quick check
state start, target, current;
int open, tail;
int i, j;
int delta;
// data set
start.vol[0] = 12; //开始时油的体积
start.vol[1] = 0;
start.vol[2] = 0;
start.depth = 0;
start.parent = -1;
target.vol[0] = 6; //结果的存放,目前是第一个瓶和第二瓶存放6
target.vol[1] = 6;
target.vol[2] = 0;
// initialization
memset(hash, 0, sizeof(hash));
queue[0] = start;
open = 0, tail = 1;
HASH(start) = 1;
// bfs search!
while (open < tail)
{
for (i=0; i <3; i++)
{
for (j=0; j <3; j++)
{
if (i != j)
{
current = queue[open];
// from i to j
delta = MIN(current.vol[i], capacity[j] - current.vol[j]);
current.vol[i] -= delta;
current.vol[j] += delta;
if (!HASH(current)) // not duplicated
{
current.depth++;
current.parent = open;
queue[tail++] = current; // enqueue
HASH(current) = 1;
if (memcmp(¤t.vol, &target.vol, sizeof(current.vol))
== 0) // got it
{
print_answer(tail - 1);
return 0;
}
}
} //end if(i != j)
} //end for(j=0;....
} //end for(i=0;...
open++; // Dequeue
}
std::cout << "no solution found" << std::endl;
return 1;
}