精华帖——八人过河的程序实现
来源:互联网 发布: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
- 精华帖——八人过河的程序实现
- 八人过河 程序 C++
- 八人过河的状态空间搜索方法
- 商人过河 Matlab程序实现
- 回溯法解决八人过河问题
- acm 人鸡米狗过河的实现
- 过河问题的代码实现
- 精华帖
- MFC截图程序的实现(八)
- latch详解——转自itpub精华帖(引)
- 商人过河问题的Java实现1
- 商人过河问题的Java实现2
- 农夫过河问题的c语言实现
- NOIP2002-过河卒—经典的dp思想
- 面试题—过河问题
- poj 1700(贪心——两人坐船过河)
- scmlife里面的ClearCase精华帖1
- scmlife里面的ClearCase精华帖2
- HDU Free DIY Tour(dp)
- Recursion
- Java中的基本类型和引用类型
- 第五周项目2——建立链栈算法库
- Unity嵌入uLua
- 精华帖——八人过河的程序实现
- WSDL文件的深入理解
- 征集意见 -- 蓝缘资金奖励政策
- 枚举法Uva725
- 【Linux】把web项目部署到Linux服务器上
- 安卓开发中遇到的奇奇怪怪的问题
- 46.[Python]使用pyolite方便管理gitolite
- Pyrhon集合与词典常用的方法
- springmvc请求时间参数报错