题目描述:
农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数, 最初,A和B桶都是空的,而C桶是装满牛奶的。有时,农民把牛奶从一个桶倒到 另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全的。由于节约, 牛奶不会有丢失
写一个程序去帮助农民找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。(翻译来源:NOCOW)
INPUT FORMAT:
单独的一行包括三个整数A,B和C。
OUTPUT FORMAT:
只有一行,升序地列出当A桶是空的时候,C桶牛奶所剩量的所有可能性
SAMPLE INPUT 1
8 9 10
SAMPLE OUTPUT 1
1 2 8 9 10
SAMPLE INPUT 2
2 5 10
SAMPLE OUTPUT 2
5 6 7 8 9 10
解题思路:
这道题的中心思想就是广度优先遍历,从初状态开始,尝试a->b,a->c,b->a,b->c,c->a,c->b;如果状态已经经历过了,则返回。下面是代码。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int a,b,c,v[20][20][20],ans[20];//v数组记录状态,ans数组记录结果
int min(int a,int b){
return a<b?a:b;
}
void judge(int ta,int tb,int tc){
if(v[ta][tb][tc])return ;//如果该状态已被标记,则return
else{
v[ta][tb][tc]=1;
if(ta==0&&ans[tc]==0)ans[tc]=1;//如果a桶没有牛奶,则标记结果
if(ta!=0&&tb<b)//a->b
judge(ta-min(ta,b-tb),tb+min(ta,b-tb),tc);
if(ta!=0&&tc<c)//a->c
judge(ta-min(ta,c-tc),tb,tc+min(ta,c-tc));
if(tb!=0&&ta<a)//b->a
judge(ta+min(tb,a-ta),tb-min(tb,a-ta),tc);
if(tb!=0&&tc<c)//b->c
judge(ta,tb-min(tb,c-tc),tc+min(tb,c-tc));
if(tc!=0&&ta<a)//c->a
judge(ta+min(tc,a-ta),tb,tc-min(tc,a-ta));
if(tc!=0&&tb<b)//c->b
judge(ta,tb+min(tc,b-tb),tc-min(tc,b-tb));
}
}
int main() {
FILE *fin = fopen ("milk3.in", "r");
FILE *fout = fopen ("milk3.out", "w");
fscanf(fin,"%d %d %d",&a,&b,&c);
int i,j;
judge(0,0,c);
for(i=0;i<c;i++)
if(ans[i])//由于c桶牛奶在初始状态下最多,所以以初始状态c桶牛奶数作为输出结尾
fprintf(fout,"%d ",i);
fprintf(fout,"%d\n",c);
exit(0);
}