#include<stdio.h>
#include<string.h>
#define N 3   //酒杯数
#define MAX_SIZES 100  //状态表中的最大状态数


 typedef struct node //边节点
{
    int adjvex;   //邻接点的位置
    node*next;  //指向下一个节点
}ARCNODE;  //邻接表中的结点类型

 typedef struct   //顶点节点
{  
    int vexdata[N];        //各酒杯的存储状态
    ARCNODE*next;      //指向下一个邻接点
}VEXNODE;//表头结点类型

 int A[MAX_SIZES];//用于存储路径的数组
int top=0;//数组中的个数 
int full[N];//各酒杯的最大容量 
int part[N];//各酒杯的当前容量 
int end[N];//最终状态

 VEXNODE s[MAX_SIZES];  //状态表
int sta;//状态表当前状态数 
  
 int sum=0;//所有解的个数
int end_vex;//结束的状态点 
bool visited[MAX_SIZES];//标记状态是否被访问
   
  
 bool compare(int a[],int b[])   //比较状态
  {  
    int i;  
    for(i=0;i<N;i++) 
        if(a[i]!=b[i])  
          return true;//两数组不相等,返回true 
    return false;//相等,返回false 
  } 
  void save(int number)  
 {   //保存状态,如果状态存在则仅仅加入领接表,如果不存在则加入状态表,并加入邻接表
     ARCNODE*p; 
     int i;  
     for(i=0;i<=sta;i++) 
     {  
        if(!compare(part,s[i].vexdata));  
             break;//该状态存在,跳出for循环
     } 
  
     if(i>sta)//将该状态加入状态表
     {  
        sta++; 
        for(int j=0;j<N;j++) 
        s[sta].vexdata[j]=part[j]; 
        s[sta].next=NULL;  
        if(!compare(part,end))  
           end_vex=sta;//该状态是最终状态,记住在状态表中的位置
     } 


     p=new ARCNODE; 
     p->adjvex=i;  
     p->next=s[number].next;  
     s[number].next=p;//加入邻接表
  } 
  
 void jisuan(int number)//求出某状态的所有邻接点
{  
    int i,j,I,J;  
    for(i=0;i<N;i++)//编号为i的酒杯与其他酒杯交换
    {   
        for(j=0;j<N;j++) 
       {  
            if(j==i)     continue;//同一酒杯,无法变换
            I=part[i];//保存i酒杯的当前的容量
            J=full[j]-part[j];//j酒杯的空闲量
               if(I<=J)//若i酒杯的当前容量小于等于j酒杯的空闲量 
               {  
                part[i]=0;  
                part[j]+=I;//将i酒杯的酒倒向j酒杯  
                save(number);//调用save()函数,保存当前的状态
                part[i]=I;  
                part[j]-=I;//恢复各酒杯的原始状态
               }  
           else//若i酒杯的当前容量大于j酒杯的空闲量
           {  
                part[i]-=J;  
                part[j]=full[j];//把j酒杯加满  
                save(number);//调用save()函数,保存当前的状态
                part[i]+=J;  
                part[j]-=J;//恢复各酒杯的原始状态
           } 
        } 
    } 
 } 
 
  
 void create()//建立状态的函数 
{  
    int i;
    int number=i; 
 printf("输入各个酒杯的容积:"); 
    for(i=0;i<N;i++)      
     scanf("%d",&full[i]); 
 printf("输入对应酒杯的起始状态:"); 
    for(i=0;i<N;i++)  
 scanf("%d",&s[0].vexdata[i]);//初始状态即状态表中的s[0] 

 printf("输入对应酒杯的最终状态:"); 
    for(i=0;i<N;i++) 
     scanf("%d",&end[i]);//所求的状态
    number=0; sta=0;   
      s[0].next=NULL; 
  
    while(number<=sta) 
    {      
        for(i=0;i<N;i++) 
          part[i]=s[number].vexdata[i];//将s[number]的状态赋给各酒杯当前的容量  
          jisuan(number);//调用jisuan(),求出该状态所有的邻接点
          number++; 
    } 
    
    for(number=0;number<=sta;number++) 
         visited[number]=false; 
 } 
  
 void prtf()   //输出路径 
{  
 int i,j,k; 
 printf("方案%d:\n",sum);  
    for(i=0;i<top;i++) 
    {  printf(" ");  
        j=A[i];//路径中的位置
        for(k=0;k<N;k++) 
        printf("%d",s[j].vexdata[k]);//输出该状态
    printf(" "); 
   }  
 printf("\n"); 
 } 
 
  
 void dfs(int v0)//深度优先搜索遍历函数 
{  
  if(!visited[v0])//判断该状态是否被访问过
   {  
        if(v0==end_vex)//判断该状态是否是最终状态
        {  
            sum++;  
           prtf();//调用输出函数
        }  
        else//若不是,深度搜索
        {  
            ARCNODE *p; 
            p=s[v0].next;  
            visited[v0]=true;//标记该状态已访问
           while(p) 
           {  
              A[top++]=p->adjvex;   //记录路径
              dfs(p->adjvex);//递归调用遍历函数
              A[--top];//清空路径
              p=p->next; 
            }  
           visited[v0]=false;//标记该状态未访问,用于其它路径中访问

        } 
  } 
 } 
  
 void findpath() 
 {  
    A[top++]=0;         //选择深度所搜遍历的起点
    dfs(0);           //进行深度所搜遍历 
} 
  
 void  main()  
 {int i,k;  
    create();        //建立模型的状态 
printf("状态表中的%d中状态:\n",sta+1); 
    for(i=0;i<=sta;i++) 
   {for(k=0;k<N;k++)  
     printf("%d",s[i].vexdata[k]); 
     printf("\t"); 
    }  
    printf("\n共得到如下解法:\n");  
    findpath();              //输出得到的解 
}