/*
* 三个水桶打水问题
* echo "17 13 5 0 0 0 14 9 0" | ./test
* 表示三个水桶容量分别为17 13 5, 初态为 0 0 0, 终态为14 9 0
*/
#include <stdio.h>
#include <stdlib.h>
// 动作预定义, 对12种动作进行预定义
#define ADDA 0
#define ADDB 1
#define ADDC 2
#define PULA 3
#define PULB 4
#define PULC 5
#define ATOB 6
#define ATOC 7
#define BTOA 8
#define BTOC 9
#define CTOA 10
#define CTOB 11
#define ACTION 12
// 桶中水的当前状态
typedef struct StatusNode
{
int a, b, c;
}Status, *pStatus;
// 桶的盛水量
typedef struct TriBottleNode
{
int a, b, c;
}TriBottle;
typedef struct ActionResultNode
{
int value;
int parent;
int action;
}ActionResult, *pActionResult;
// 状态数
int maxStatus = 0;
// 三个桶最多的盛水量
TriBottle bottles = { 0 };
// 辅助计算
int cal[] = { 0, 0, 0 };
char *flagStatus;
ActionResult *ans;
/*
* 计算当前桶中水的权值
*/
int GetValue(Status sa)
{
return sa.a * cal[0]
+ sa.b * cal[1]
+ sa.c * cal[2];
}
/*
* 根据权值得到当前桶中水的状态
*/
Status GetStatus(int value)
{
Status ans = {0, 0, 0};
ans.a = value / cal[0];
ans.b = value % cal[0] / cal[1];
ans.c = value % cal[0] % cal[1];
return ans;
}
/*
* 初始化三个水桶
*/
void InitBottle(int a, int b, int c)
{
bottles.a = a, bottles.b = b, bottles.c = c;
cal[0] = (b + 1) * (c + 1);
cal[1] = c + 1, cal[2] = 1;
maxStatus = (a + 1) * (b + 1) * (c + 1);
flagStatus = calloc(maxStatus, sizeof(char));
ans = calloc(maxStatus, sizeof(ActionResult));
}
/*
* 结束函数,释放空间等操作
*/
void EndFunction()
{
free(ans);
free(flagStatus);
printf("%s\n", "程序运行结束!");
}
/*
* 根据action计算下一状态并返回
*/
Status GetNextStatus(Status sa, int action)
{
int sum = 0;
Status ans = sa;
switch (action)
{
case ADDA: ans.a = bottles.a; break;
case ADDB: ans.b = bottles.b; break;
case ADDC: ans.c = bottles.c; break;
case PULA: ans.a = 0; break;
case PULB: ans.b = 0; break;
case PULC: ans.c = 0; break;
case ATOB: sum = ans.a + ans.b;
if (sum <= bottles.b) ans.a = 0, ans.b = sum;
else ans.a = sum - bottles.b, ans.b = bottles.b;
break;
case ATOC: sum = ans.a + ans.c;
if (sum <= bottles.c) ans.a = 0, ans.c = sum;
else ans.a = sum - bottles.c, ans.c = bottles.c;
break;
case BTOA: sum = ans.b + ans.a;
if (sum <= bottles.a) ans.b = 0, ans.a = sum;
else ans.b = sum - bottles.a, ans.a = bottles.a;
break;
case BTOC: sum = ans.b + ans.c;
if (sum <= bottles.c) ans.b = 0, ans.c = sum;
else ans.b = sum - bottles.c, ans.c = bottles.c;
break;
case CTOA: sum = ans.c + ans.a;
if (sum <= bottles.a) ans.c = 0, ans.a = sum;
else ans.c = sum - bottles.a, ans.a = bottles.a;
break;
case CTOB: sum = ans.c + ans.b;
if (sum <= bottles.b) ans.c = 0, ans.b = sum;
else ans.c = sum - bottles.b, ans.b = bottles.b;
break;
}
return ans;
}
/*
* 主要的计算过程
*/
void fun(int start, int end)
{
int posstart = 0, posend = 1;
flagStatus[start] = 1;
ans[posstart].value = start;
while (posstart < posend)
{
int value = ans[posstart].value;
if (value == end) break;
Status status = GetStatus(value);
for (int action = 0;action < ACTION;action++)
{
Status tmp = GetNextStatus(status, action);
int tmpValue = GetValue(tmp);
if (flagStatus[tmpValue]) continue;
ans[posend].value = tmpValue;
ans[posend].parent = value;
ans[posend].action = action;
posend += 1;
flagStatus[tmpValue] = 1;
}
posstart += 1;
}
if (posstart >= posend)
{
printf("%s\n", "未找到解决方案!");
return;
}
int count = 0;
int parent = ans[posstart].value;
for (int i = posstart;i >= 0;i--)
{
if (parent == ans[i].value)
{
Status tmp = GetStatus(parent);
printf("[%03d] : %02d%3d%3d%3d\n", count, ans[i].action, tmp.a, tmp.b, tmp.c);
parent = ans[i].parent;
// 统计次数
count += 1;
}
}
printf("至少需要%d次移动!\n", count - 1);
}
/*
* 主函数
*/
int main(int argc, char *argv[])
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
InitBottle(a, b, c);
scanf("%d%d%d", &a, &b, &c);
Status beg = {a, b, c};
scanf("%d%d%d", &a, &b, &c);
Status end = {a, b, c};
fun(GetValue(beg), GetValue(end));
EndFunction();
return 0;
}