1. 程式人生 > >精華帖——八人過河的程式實現

精華帖——八人過河的程式實現

題目:

一家六口,一個爸爸,一個媽媽,倆兒子,倆女兒,還有一個警察,一個壞蛋,過一條河。

爸爸不在媽媽傷害兒子,媽媽不在爸爸傷害女兒,警察不在壞蛋傷害一家六口。

只有媽媽爸爸警察會開船,一次只能過兩個人,只有一艘船。

用程式實現怎麼過河。

思路見程式:

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;
	else
		return 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;
	else
		return 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;//自己與自己的距離為0
			else 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;
				else
					matrix[i][j]=MAX;//表示節點間不相連

			}
			else
				matrix[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!!!