C语言智力问题。。。。。。

(1)项目描述
游戏规则:一家6口(爸爸、妈妈、两个女儿、两个儿子)及警察和小偷要从河这边渡到河对岸。在河这边仅有一艘小舢板可以把他们载到对岸。可是,只有爸爸、妈妈和警察能够驾船,不论成人与小孩,每程只能承载二人。在渡河过程中,你要避免以下三种情况的发生:
(1)当警察与小偷分开时,小偷会伤害一家6口;
(2)当爸爸看见妈妈离开时,爸爸便会教训女儿;
(3)当妈妈看见爸爸离开时,妈妈便会教训儿子。
(2)解决思路
【数据结构建模】
一共八个人,每个人都有两个状态(左岸和右岸)。我们把八个人在左岸的状态记为[0,0,0,0,0,0,0,0],都在右岸时记为[1,1,1,1,1,1,1,1]。那么,本项目其实就是要寻找一个从[0,0,0,0,0,0,0,0,0]到[1,1,1,1,1,1,1,1]的解。
这个状态我们其实可以开辟一个8个元素的数组。另外还需要设置一个变量代表船的状态。因为还要打印结果,所以在搜索的过程中还需要一个结构体数组存储每次渡河的人是谁(可能是一个人,也可能是2个人),当然,也可以建立2个一维数组代替结构体数组。
接下来可以选择深度优先搜索或者宽度优先搜索来进行搜索,每个状态的限制条件根据题意可以得出。
最后遍历存储渡河人员的数组,并打印出结果。
其实每个人的状态(包括船的状态都是0或者1),所以其实用一个int型 就可以了。状态转移全部使用位运算。
【建立模型】
使用2的整数次幂表示不同人,所以使用一个整数表示当前的局面, 255为初始,0为结束。
{POLICE=0x80,THIEF=0x40,DAD=0x20,BOY1=0x10,BOY2=0x8,MOM=0x4,GIRL1=0x2,GIRL2=0x1,ALL=0xff,OK=0};
(3)问题扩展
将数组存储状态,变换为用一个字节来表示各个人的状态,然后采用位运算方式进行升级。

过河顺序可以参考下代码,运行出的结果就是过河顺序:

#include<stdio.h>
#include<stdlib.h>
 int c1(int x,int y)
 {
     return (x&y)==x;
 }
 int c2(int x)
 {
     if(x<128&&x>64)return 0;
     if(c1(32,x)&&!c1(4,x)&&(c1(2,x)||c1(1,x)))
         return 0;
     if(!c1(32,x)&&c1(4,x)&&(c1(16,x)||c1(8,x)))
         return 0;
     return 1;
 }
 static int a[]={128+64,128+32,128+16,128+8,128+4,128+2,129,128,32+16,32+8,32+4,32,4+2,4+1,4};  
void f(int x,int * pa,int n)                                
{
    int i;
 
if(n>20) return;            
if(x==0)
{
    int i;
    for(i=0;i<n;i++)
        printf("%d\n",pa[i]);
    exit(0);
}

for(i=0;i<15;i++)
{ 
  if(n&&a[i]==pa[n-1]) continue;
  if(n%2==0)
  {
     if(!c1(a[i],x)) continue;
     if(!c2(x-a[i]))  continue; 
     if(!c2(255-x+a[i]))  continue;
     pa[n]=a[i];      
     f(x-a[i],pa,n+1);
 }
 else
 {
     if(!c1(a[i],255-x)) continue;
     if(!c2(255-x-a[i]))  continue; 
     if(!c2(x+a[i]))  continue; 
     pa[n]=a[i];     
     f(x+a[i],pa,n+1);
 }
}
}
//jc 128  
//xt  64
//bb  32
//de  16
//ee  8
//mm  4
//dg  2
//2g  1 
int main()
{
    int pa[1111];               
    f(255,pa,0);                
}