题目大概99.9%的人都听说过:
两个杯子(A 、B)用不完的水,一共有六种操作:1、加满A(B),2、清空A(B),3、将A(B)中的水倒入B(A)(加满为止)。不断的做这些操作,最终达到B中剩下指定量的水。
输入: A的容积,B的容积,以及最终要求B中剩下多少水(不会出现无解的情况)
输出: 操作步骤(这里并不要求最少步骤)
考虑回溯搜索,这里显然有很多可以剪枝的地方:
1、不能出现重复的情况
2、清空后加满不如直接加满,加满后清空不如直接清空
3、操作后不能出现全满和全空的情况
Accepted | 1005 | C++ | 00:00.06 | 4300K |
#include<stdio.h>
#include
<string.h>
#define B if(blacklist[a][b] == 0) /

...
{ /
stack[top][0] = a; /
stack[top][1] = b; /
top++; /
blacklist[a][b]++; /
continue; /
}
/
else
/

...
{ /
a = a1; /
b = b1; /
}
int
ca,cb,n;
int stack[100][2
];
int
top;
int blacklist[1000][1000
];
int getoperate(int
index)

...
{
if(index > 0)

...{
int t = stack[index - 1][0] + stack[index - 1][1];
int t1 = stack[index][0] + stack[index][1];
if(t == t1)
if(stack[index][0] == ca)
return 2;
else if(stack[index][1] == 0)
return 2;
else return 1;
else if(t1 > t)
return stack[index][0] == ca ? 3 : 4;
else if(t1 < t)
return stack[index][0] == 0 ? 5 : 6;
}
return 0;
}
void
print()

...
{
for(int i = 1; i < top; i++)

...{
switch(getoperate(i))

...{
case 1:
printf("pour A B");break;
case 2:
printf("pour B A");break;
case 3:
printf("fill A");break;
case 4:
printf("fill B");break;
case 5:
printf("empty A");break;
case 6:
printf("empty B");break;
}
printf(" ");
}
}
void
search()

...
{
int a,b,a1,b1;
a = b = 0;
a1 = b1 = 0;
memset(blacklist,0,sizeof(blacklist));
memset(stack,0,sizeof(stack));
top = 0;
stack[top][0] = 0;
stack[top][1] = 0;
blacklist[ca][cb] = 1;
blacklist[0][0] = 1;
top++;
while(1)

...{
if(a - cb + b== n)

...{
print();
printf("pour A B empty B pour A B ");
return;
}
if(b - ca + a == n)

...{
print();
printf("pour B A ");
return;
}

a1 = a;
b1 = b;
if(a > cb - b)//1 pour a b

...{
a = a - cb + b;
b = cb;
}
else

...{
b = a + b;
a = 0;
}
B

a1 = a;
b1 = b;
if(b > ca - a)//2 pour b a

...{
b = b - ca + a;
a = ca;
}
else

...{
a = a + b;
b = 0;
}
B
if(getoperate(top - 1) != 5)//3 fill a

...{
a1 = a;
b1 = b;

a = ca;
B
}
if(getoperate(top - 1) != 6)//4 fill b

...{
a1 = a;
b1 = b;
b = cb;
B
}

if(getoperate(top - 1) != 3)//5 empty a

...{
a1 = a;
b1 = b;
a = 0;
B
}
if(getoperate(top - 1) != 4)//6 empty b

...{
a1 = a;
b1 = b;
b = 0;
B
}
top--;//back
a = stack[top - 1][0];
b = stack[top - 1][1];
}
}
void
solve()

...
{
int i;
if(cb == n)

...{
printf("fill B ");
return;
}
if(n % ca == 0)

...{
for(i = 0; i < n/ca; i++)
printf("fill A pour A B ");
return;
}
if(cb - ca == n)

...{
printf("fill B pour B A ");
return;
}
search();
}
int
main()

...
{
#ifndef ONLINE_JUDGE
freopen("1005.txt","r",stdin);
#endif
while(scanf("%d%d%d",&ca,&cb,&n) != EOF)

...{
solve();
printf("success ");
}
#ifndef ONLINE_JUDGE
fclose(stdin);
#endif
return 0;
}