求解木桶倒水问题

问题:现在有三个木桶容量分别为8,5,3升,最初容量为8升的木桶内装满了水,另外两个木桶内为空。三个木桶都没有体积刻度,现在需要将大水桶的8升水等分成两份,每份4升水。列出所有可行的方案。(附不能借助除这三个木桶的其他桶接水)


思路分析:这个问题的思路和农夫过河问题的思路基本类似,只是问题的模型改变了,可以参考另一篇文章求解农夫过河问题


C语言代码:

#include<stdio.h>
#define maxsize 100

typedef struct{         //定义3个木桶组的结构体 
    int capability[3];  //记录容量 

    int contain[3];     //记录容积 

}group; 

int judge(group route[maxsize],int location,group newone) //判断新状态在该路径上是否产生重复 
{                                                         //有重复返回1,没有重复返回0 
    int i;
    for(i=0;i<=location;i++)
    {
        if(route[i].contain[0]==newone.contain[0]&&route[i].contain[1]==newone.contain[1]&&route[i].contain[2]==newone.contain[2])
        {
            return 1;
        }
    }
    return 0;
}

void print(group route[maxsize],int location) //输出某路径记录的方案 
{
   int i;
   for(i=0;i<=location;i++)
   {
     printf("%d %d %d\n",route[i].contain[0],route[i].contain[1],route[i].contain[2]);
   }
   printf("\n");

}

void process(group someone,group route[maxsize],int location) //算法核心,利用深度优先搜索进行遍历,找到满足条件的路径就立刻输出 
{
    if(someone.contain[0]==4&&someone.contain[1]==4) //如果把8升水平分完成 
    {
        print(route,location); //输出该路径的方案 
    }
    else
    {
        int i,s,e,o;
        for(i=0;i<=5;i++) //倒水的6种方案 
        {
            switch(i)
            {
                case 0:
                s=0;e=1;o=2;break; //第一个桶往第二个桶里倒 
                case 1:
                s=0;e=2;o=1;break; //第一个桶往第三个桶里倒 
                case 2:
                s=1;e=0;o=2;break; //第二个桶往第一个桶里倒 
                case 3:
                s=1;e=2;o=0;break; //第二个桶往第三个桶里倒 
                case 4:
                s=2;e=0;o=1;break; //第三个桶往第一个桶里倒 
                case 5:
                s=2;e=1;o=0;break; //第三个桶往第二个桶里倒 
            }

                if(someone.contain[s]!=0) //如果要出水的桶不为空 
                {
                    if(someone.contain[e]<someone.capability[e]) //如果要接水的桶还有剩余空间 
                    {
                        group newone=someone; //生成一个新的状态 
                        group newroute[maxsize]; //生成一个新的路径 
                        int i;
                        for(i=0;i<=location;i++) //新的路径先把原来的路径拷贝进来 
                        {
                          newroute[i]=route[i];
                        }
                        if(someone.contain[s]<=(someone.capability[e]-someone.contain[e])) //如果出水的桶需要把水全部倒入接水的桶中 
                        {
                            newone.contain[s]=0;
                            newone.contain[e]=someone.contain[s]+someone.contain[e];
                            newone.contain[o]=someone.contain[o];
                            if(judge(route,location,newone)==0) //如果新状态没有重复过 
                            {
                                newroute[location+1]=newone; //把新状态记录进新路径中 
                                process(newone,newroute,location+1); //从新状态即新路径出发继续深度优先搜索下去 
                            }
                        }
                        else //如果出水的桶只能把部分水倒入接水的桶中 
                        {
                            newone.contain[s]=someone.contain[s]-(someone.capability[e]-someone.contain[e]);
                            newone.contain[e]=someone.capability[e];
                            newone.contain[o]=someone.contain[o];
                            if(judge(route,location,newone)==0) //如果新状态没有重复过 
                            {
                                newroute[location+1]=newone; //把新状态记录进新路径中 
                                process(newone,newroute,location+1); //从新状态即新路径出发继续深度优先搜索下去 
                            }
                        }
                    }
                }
        }
    }
}


int main()
{
    group origin; 
    origin.capability[0]=8;
    origin.capability[1]=5;
    origin.capability[2]=3;
    origin.contain[0]=8;
    origin.contain[1]=0;
    origin.contain[2]=0; //初始化木桶组的状态 

    group route[maxsize];
    int location=0;
    route[location]=origin; //初始化路径,location记录路径最新状态的位置(下标) 

    process(origin,route,location); //从初始状态出发查找所有可行方案 

} 

代码运行结果:

8 0 0
3 5 0
0 5 3
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
4 1 3
4 4 0

8 0 0
3 5 0
3 2 3
0 5 3
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
4 1 3
4 4 0

8 0 0
3 5 0
3 2 3
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
4 1 3
4 4 0

8 0 0
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
0 5 3
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
4 1 3
4 4 0

8 0 0
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
0 5 3
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
4 1 3
4 4 0

8 0 0
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
4 1 3
4 4 0

8 0 0
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
4 4 0

8 0 0
3 5 0
3 2 3
6 2 0
6 0 2
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
4 1 3
4 4 0

8 0 0
5 0 3
0 5 3
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
4 4 0

8 0 0
5 0 3
5 3 0
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
4 4 0

8 0 0
5 0 3
5 3 0
2 3 3
0 5 3
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
4 4 0

8 0 0
5 0 3
5 3 0
2 3 3
2 5 1
0 5 3
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
4 4 0

8 0 0
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
4 4 0

8 0 0
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
4 1 3
0 5 3
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
4 4 0

8 0 0
5 0 3
5 3 0
2 3 3
2 5 1
7 0 1
7 1 0
4 1 3
4 4 0

8 0 0
5 0 3
5 3 0
2 3 3
2 5 1
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
4 4 0

总共有16种可行的方案,其中最快,代价最小的方案是:

8 0 0
3 5 0
3 2 3
6 2 0
6 0 2
1 5 2
1 4 3
4 4 0

猜你喜欢

转载自blog.csdn.net/lovecaicaiforever/article/details/82288277