acm 使用穷举法解决人鸡狗米过河的问题

来源:互联网 发布:淘宝机锋市场怎么样 编辑:程序博客网 时间:2024/06/01 10:21

在网上看了一到关于人鸡米狗过河的数学建模题。然后对其进行编码实现。方法参考来源于:http://blog.sina.com.cn/s/blog_6c138b4701011own.html

以下是具体的代码:

 

#include<iostream>
#include<math.h>
#include<bitset>
#define STATUS  16
#define NUM 4
#define NUMOFSTEP   20
using namespace std;
int graph[16][16];
bitset<16>     isCan;                   //16种状态向量
bitset<4>     d[4];                     //4种可行的渡河方式    运算向量
bitset<4> map[16];
bool used[16];                   //对图经行遍历的时候要用到,防止对已经遍历的节点再次遍历
int step=0;
int action[20];//记录最大的步骤是20
void init()  
{
   /*
   使用穷举法将可行的状态列出来。1表示在南岸 0表示在北岸 (ren ,,gou,ji ,mi)
   (1, 1, 1, 1),(1, 1, 1, 0),(1, 1, 0, 1),(1, 0, 1, 1),(1, 0, 1, 0);
   (,0, 0, 0, 0),(0, 0, 0, 1),(0, 0, 1, 0),(0, 1, 0, 0),(0,1,0,1).
   渡河的向量
(1, 1, 0, 0),(1, 0, 1, 0),(1, 0, 0, 1),(1, 0, 0, 0)


 */


 isCan[15]=1;  isCan[0]=1;
 isCan[14]=1;  isCan[1]=1;
 isCan[13]=1;   isCan[2]=1;
 isCan[11]=1;   isCan[4]=1;
 isCan[10]=1;    isCan[5]=1;

 d[0][3]=1;
 d[0][2]=1;


 d[1][1]=1;
 d[1][3]=1;

 d[2][0]=1;
 d[2][3]=1;
 d[3][3]=1;

 memset(used,0,sizeof(used));

}
void  initMap()  //对进行初始化
{
   init();
 bitset<4>  t;
 int a,b,c,d;
 for(a=0;a<2;a++)
  for(b=0;b<2;b++)
   for(c=0;c<2;c++)
    for(d=0;d<2;d++)
    {
     t[3]=a;
     t[2]=b;
     t[1]=c;
     t[0]=d;

     int len=t.to_ulong();
     map[len]=t;
    }


}
void initGraph()  //以当前的向量状态进行递归
{
 
 int i,j,x,y;
 bitset<4>  tempt;
 for(i=0;i<16;i++)
 {
  x=map[i].to_ulong();
      for(j=0;j<4;j++)
   {
             tempt=map[i];
    bitset<4>  t;
    tempt^=d[j];   //对状态向量进行运算向量的异或处理
            y=tempt.to_ulong();// 得到的状态是否可行
   if(isCan[y]==1)
    graph[x][y]=1;

           else
      graph[x][y]=0;

   }//#end for j
 
 }//#end for  i
  
}
void print()
{
 

 cout<<endl;
 int m,n=15;
 
 for(int j=0;j<step;j++)
 {
  if(j%2)
   cout<<"回来:";
  else
   cout<<endl<<"去:";
  m=n;
  n=action[j];
  int t=-1;
  for(int loop=0;loop<3;loop++)
  {
   if(map[m][loop]!=map[n][loop])
   {t=loop;break;}
               
  }
  
  switch(t)
  {
  case 0:       cout<<"人 和  米\t";break;
  case 1:       cout<<"人 和  鸡 \t" ; break;
  case 2:       cout<<"人 和  狗\t";break;
  default  :    cout<<"   人    \t";break;
  }
 }
 cout<<endl;
 cout<<"already over\n"<<endl;
}
void   findOut(int begin)  //递归遍历图,找出从graph[begin]至graph[end]的路径
{
    int  i,j;
 used[begin]=1;
    if(step>=NUMOFSTEP*2)
  return ;
 if(begin==0)  //当图表示从0开始的时候表明已经到达目的了。step必须为奇数
 
  print();
    
 for(i=0;i<16;i++)
 {
     
  if(graph[begin][i]&&used[i]==0)
  {
   action[step++]=i;
   findOut(i);
   step--;
   used[i]=0;
  }
 // 返回来的时候
  
 }


}

 

int main()
{
 int i,j;
initMap();


initGraph();
/*
for(i=0;i<16;i++)
{
for(j=0;j<16;j++)
   cout<<graph[i][j]<<"  ";
cout<<endl;
}
*/
findOut(15);
}

 

原创粉丝点击