精华帖——八人过河的程序实现

来源:互联网 发布:cutecom串口发送数据 编辑:程序博客网 时间:2024/06/06 00:33

题目:

一家六口,一个爸爸,一个妈妈,俩儿子,俩女儿,还有一个警察,一个坏蛋,过一条河。

爸爸不在妈妈伤害儿子,妈妈不在爸爸伤害女儿,警察不在坏蛋伤害一家六口。

只有妈妈爸爸警察会开船,一次只能过两个人,只有一艘船。

用程序实现怎么过河。

思路见程序:

include<iostream>#include <vector>#include <stdio.h>using namespace std;/*总体思路:用一个9位的整数表示,当前所处的状态,最高位表示河的左岸或者右岸。低8位依次表示警察,犯人,父亲母亲,2个儿子,2个女儿;一次渡河可以看成是2个状态之间的转移。总体分两步进行;Step 1:先算出转移矩阵Step 2:利用迪杰斯特拉算出,源点到终点最短路径,所经历的结点。*/#define MAX 10000//结点间的最大值,表示两个状态不能转换#define N 512//表示状态向量,以9bit值表示。eg:0 1111 1111表示开始状态,所有的8个人在河的左岸。const int lrmask=1<<8;//0表示在河的左岸,1表示在河的右岸。const int cap= 1<<7;//表示警察的状态const int criminal=1<<6;//表示犯人的状态const int father=1<<5;//表示爸爸的状态const int mother=1<<4;//表示妈妈的状态const int son=3<<2;//表示两个儿子的状态const int daughter=3;//表示两个女儿的状态bool is_possible_state(int x)//判断某个状态是否满足规则{if ((x&criminal)&&(!(x&cap))&&(x&(father+mother+son+daughter)))//表示警察不在的时候,犯人不能与6口家人在一起return false;if ((x&father)&&(!(x&mother))&&(x&daughter))//表示妈妈不在,爸爸不能与女儿在一起return false;if ((x&mother)&&(!(x&father))&&(x&son))//表示爸爸不在,妈妈不能与儿子在一起return false;elsereturn true;//其它为有效状态}bool is_possible_vec(unsigned char x)//判断在船上的状态{int num=0;int tmp=x;if (x==0)//表示状态向量的值为0 ,没人乘船,无效状态return false;while(tmp){num++;if (num>2)//当多余2个人乘船,无效状态return false;tmp=tmp&(tmp-1);//判断几个人乘船}if ((x&criminal)&&(!(x&cap))&&(x&(father+mother+son+daughter)))//判断该状态是否满足规则return false;if ((x&father)&&(!(x&mother))&&(x&daughter))return false;if ((x&mother)&&(!(x&father))&&(x&son))return false;elsereturn true;//满足情况,返回true.} void Dijkstra(int v, int **dist,int D[N],int p[N],int s[N])    {     int i, j, k, v1, min, max=10000, pre;           v1=v;       for( i=0; i<N; i++)                 {    D[i]=dist[v1][i];           if( D[i] != MAX )  p[i]= v1+1;           else p[i]=0;           s[i]=0;       }      s[v1]=1;                                for( i=0; i<N-1; i++)          {    min=10001;            for( j=0; j<N-1; j++)                if ( ( !s[j] )&&(D[j]<min) )                             {min=D[j];                           k=j;                        }                  s[k]=1;     for(j=0; j<N; j++)       if ( (!s[j])&&(D[j]>D[k]+dist[k][j]) )         {D[j]=D[k]+dist[k][j];           p[j]=k+1;                                      }              }                                           for(i=511; i<512; i++) //仅输出从源点状态0 1111 1111 到终点状态 1 0000 0000的路径            {                  printf(" %d : %d ", D[i], i);                  pre=p[i];               while ((pre!=0)&&(pre!=v+1))              {    printf ("<- %d ", pre-1);                   pre=p[pre-1];               }              printf("<-%d \n", v);           }  } int main(){int  **matrix=(int **)malloc(N*sizeof(int *));//创建二维状态矩阵matrix[N][N]for (int i=0;i<N;i++){matrix[i]=(int *)malloc(N*sizeof(int));}//计算矩阵的值,即计算结点之间的路径。1表示可以连接,0表示自己与自己路径,MAX表示结点间不相连接for(int i=0;i<N;i++){for (int j=0;j<N;j++){if (i==j)matrix[i][j]=0;//自己与自己的距离为0else if(((i&lrmask)^(j&lrmask))&&is_possible_state(~j)&&is_possible_state(i)&&is_possible_state(~j)&&is_possible_state(j)){ //当满足i,j分别为某次转移前左岸的状态与转移后右岸的状态; //~i和~j分别表示某次转移前右岸的状态与转移后左岸的状态unsigned char i0=i%256;//i0,j0分别表示状态向量值的后八位,即八个人在左岸与右岸的状态unsigned char j0=j%256;unsigned char tmp=~i0^j0;//tmp表示转移向量值,即某次那些人状态发生了改变//在满足上述情况的基础上,tmp转移向量值有效if(((unsigned char)i0>(unsigned char)(~j0))&&is_possible_vec(tmp)&&!(tmp-(tmp&i0)))matrix[i][j]=1;elsematrix[i][j]=MAX;//表示节点间不相连}elsematrix[i][j]=MAX;//表示节点间不相连}}int D[N]={0};//数组D表示经过了几个结点      int p[N]={0};//数组P存储的是从源点到终点经过了那些结点      int s[N]={0};//保存已经找到的结点      int num=0; Dijkstra(255,matrix,D,p,s);//运用迪杰斯特拉算法,初始状态从0 1111 1111开始}
题外话:这是面试某狗测试岗的课外作业。哈哈~~

霸面某狗,遇到一个很nice的面试官,问的问题虽然回答的不是特别好,但是却让我大开眼界,原来类似智力题这么好玩!!!哈哈~~

下午3点结束面试,拿到的题目——之前听过没做过的题目。来不及马上做,又去赶另一家互联网的面试。唉,一波面试向我袭来,有些措手不及。

晚上回去搜一下,原来是个小游戏。哈哈,从没想过自己能写出个游戏。

整个思考过程表示很痛苦,痛并快乐着。整个晚上很high,熬到夜里3点多。。。竟然不感觉困。。。

因为刚开始思路有点绕路了,耽误些时间,提交时间晚了2个多小时。所以,这可能也是没通过的原因之一。

不过,找到了许久以来没有的学习兴趣与热情。。。。哈哈,很nice!!!


0 0
原创粉丝点击