昨天在CSDN社区的C语言版看到了这样一个问题:
有3个水杯A、B、C,容量分别为80L,50L,30L。现在有80L水装入A(B和C杯为空),A可以向B或C倒水。倒水要求:要么把别的杯子倒满,要么就自己倒空,倒水方向任意。最后要达到的目的是A杯有40L水,B杯有40L水,C杯无水。
看完以后很有兴趣,就写了自己的算法。虽然代码行数很多,但思路其实很简单:
- 找出当前状态下所有可能的路径。
- 按深度优先依次遍历路径,直到成功。
- 如果产生回路,则放弃这条路径。
#include <stdio.h>
#define MAXSTEP 100 /* the maximum number of steps allowed */
#define MAXPATH 6 /* the maximum number of path choices */
/* Choices when pouring water from one cup to another */
enum Path
{
AToB,
AToC,
BToC,
BToA,
CToA,
CToB
};
/* State of the 3 cups */
struct state
{
int A;
int B;
int C;
};
struct state steps[MAXSTEP]; /* stores the steps of the process */
int sindex = 0; /* indicates the next step position */
int paths[MAXPATH]; /* stores the choices in a specified state */
int pindex = 0; /* indicates the next choice position */
/* function declaration */
int Run(struct state s);
void FindPaths(struct state s);
void Move(int index, struct state *s);
int BackToStart(struct state s);
main()
{
struct state s = {80, 0, 0}; /* initial state */
int i;
steps[sindex++] = s; /* store the first step */
if (Run(s)) /* print the steps if succeed */
{
for (i = 0; i < sindex; i++)
printf("(%d, %d, %d)/n", steps[i].A, steps[i].B, steps[i].C);
}
}
/* Starts the process of pouring water */
int Run(struct state s)
{
int i, index;
struct state s1;
FindPaths(s); /* find all the choices in a specified state */
/* back up the variables */
index = sindex;
s1 = s;
/* go through all the choice */
for (i = 0; i < pindex; i++)
{
/* set back to the state when starting the loop */
sindex = index;
s = s1;
Move(i, &s); /* move water according to the choice */
if (BackToStart(s)) /* drop the path if it goes to the start point */
continue;
else
steps[sindex++] = s; /* store it if it's a new step */
/* succeed or keep running */
if ((s.A == 40 && s.B == 40 && s.C == 0) || Run(s))
return 1;
}
return 0; /* should not come here */
}
/* Finds all the choices in a specified state */
void FindPaths(struct state s)
{
pindex = 0; /* reset the indicator */
if (s.A != 0 && s.B != 50)
paths[pindex++] = AToB;
if (s.A != 0 && s.C != 30)
paths[pindex++] = AToC;
if (s.B != 0 && s.C != 30)
paths[pindex++] = BToC;
if (s.B != 0 && s.A != 80)
paths[pindex++] = BToA;
if (s.C != 0 && s.A != 80)
paths[pindex++] = CToA;
if (s.C != 0 && s.B != 50)
paths[pindex++] = CToB;
}
/* Moves water from one cup to another */
void Move(int index, struct state *s)
{
/* only two possibilites: 1. empty the source cup;
2. fill the destination cup. */
switch (paths[index])
{
case AToB:
if (s->A + s->B <= 50) /* empty the source cup */
{
s->B += s->A;
s->A = 0;
}
else /* fill the destination cup */
{
s->A -= 50 - s->B;
s->B = 50;
}
break;
case AToC:
if (s->A + s->C <= 30)
{
s->C += s->A;
s->A = 0;
}
else
{
s->A -= 30 - s->C;
s->C = 30;
}
break;
case BToC:
if (s->B + s->C <= 30)
{
s->C += s->B;
s->B = 0;
}
else
{
s->B -= 30 - s->C;
s->C = 30;
}
break;
case BToA:
if (s->B + s->A <= 80)
{
s->A += s->B;
s->B = 0;
}
else
{
s->B -= 80 - s->A;
s->A = 80;
}
break;
case CToA:
if (s->C + s->A <= 80)
{
s->A += s->C;
s->C = 0;
}
else
{
s->C -= 80 - s->A;
s->A = 80;
}
break;
case CToB:
if (s->C + s->B <= 50)
{
s->B += s->C;
s->C = 0;
}
else
{
s->C -= 50 - s->B;
s->B = 50;
}
break;
}
}
/* Checks if the state is same as a state before */
int BackToStart(struct state s)
{
int i;
for (i = 0; i < sindex; i++)
{
if (steps[i].A == s.A && steps[i].B == s.B && steps[i].C == s.C)
return 1;
}
return 0;
}
本文介绍了一个使用C语言实现的水量分配问题解决方案。通过深度优先搜索算法,找到从80L水杯向50L和30L水杯分配水,最终使80L水杯和50L水杯各含40L水的过程。

854

被折叠的 条评论
为什么被折叠?



