• 野人与传教士问题


    1.题目简述:有N个传教士和N个野人要过河。如今有一条船仅仅能承载N个人(包含野人),在不论什么时刻,假设有野人和传教士在一起。必需要求传教士的人数多于或等于野人的人数。
    2.解答描写叙述:这题我通过人工仅仅能基于生产式系统解答。事实上就是算法中说的深度优先搜索算法。在自己归纳策略集的时候发现当N=1时一次就过去了,当N=2时仅仅有两条规则,当N=3时有5条规则。当N=4时有9条规则。当N=5时有14条规则。所以取N=3时比較便于表达又有代表性(当然河对岸的规则同样)。
    3.详细代码:
    代码例如以下,全部思想基本标注:

     

    #include "stdafx.h"
    #include<process.h> 
    #include<stdio.h>
    #include <stdlib.h>
    #define NULL 0
    #define TRUE 1
    #define FALSE 0
    #define OK 1
    #define ERROR 0
    
    typedef struct
    {
    	int m; //传教士人数
    	int c; //野人人数
    	int b; //船的位置变量
    }QElemType; /* 定义队列的数据元素类型QElemType为结构体类型 */
    typedef struct _Rule
    {
    	int m;//传教士人数
    	int c;//野人人数
    }Rule;
    
    Rule rule[5] = {{1,1}, {1,0}, {0,1}, {2,0}, {0,2}};  // 规则集e
    
    typedef struct QNode
    {
    	QElemType data;
    	struct QNode *next;
    }QNode,*QueuePtr;//节点结构体
    
    typedef struct
    {
    	QueuePtr front,rear; //队头、队尾指针 
    }LinkQueue;
    
    /* 构造一个空队列Q */
    void InitQueue(LinkQueue *Q)
    { 
    	(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));
    	if(!(*Q).front)
    		exit(0);
    	(*Q).front->next=NULL;
    }
    
    /* 若队列不空,删除Q的队头元素,用e返回其值。并返回OK。否则返回ERROR */
    int DeQueue(LinkQueue *Q,QElemType *e)
    { 
    	QueuePtr p;
    	if((*Q).front==(*Q).rear)
    		return ERROR;
    	p=(*Q).front->next;
    	*e=p->data;
    	(*Q).front->next=p->next;
    	if((*Q).rear==p)
    		(*Q).rear=(*Q).front;
    	free(p);
    	return OK;
    }
    
     /* 插入元素e为Q的新的队尾元素 */
    void EnQueue(LinkQueue *Q,QElemType e)
    {
    	QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
    
    	if(!p) 
    		exit(0);
    	p->data=e;
    	p->next=NULL;
    	(*Q).rear->next=p;
    	(*Q).rear=p;
    }
    
    /* 若Q队列。有给定节点返回true。否则返回false */
    int cmp(LinkQueue *Q,QElemType e){ 
    	QueuePtr p=(*Q).front->next;
    	while(p!=NULL){
    
    		if(p->data.m==e.m&&p->data.c==e.c&&p->data.b==e.b)
    			return TRUE;
    
    
    		else p=p->next;
    	}
    	return FALSE;
    }
    
    /* 若Q为空队列,则返回TRUE,否则返回FALSE */
    int QueueEmpty(LinkQueue Q)
    { 
    	if(Q.front->next==NULL)
    		return TRUE;
    	else
    		return FALSE;
    }
    
    void main(){
    	LinkQueue open,closed;  //定义首尾指针
    	QueuePtr p;  //定义节点指针
    	int i;
    	InitQueue(&open);  //初始化open队列
    	InitQueue(&closed);   //初始化closed队列
    	QElemType s={3,3,1},e,e1;   //初始化初始节点s,3个传教士,3个野人,船在左岸
    	EnQueue(&open,s);    //将s入列
    	while(!QueueEmpty(open)){
    		DeQueue(&open,&e);
    		EnQueue(&closed,e);
    		if(e.m==0&&e.c==0&&e.b==0)//推断条件控制策略是否结束
    		{printf("成功!");
    		continue;}
    		for(i=0;i<5;i++)  //由于控制策略仅仅有5步所以这里循环5次
    		{e1.m=e.m,e1.c=e.c,e1.b=e.b;
    		if(e1.b==1)//船在左岸,对数据库做减法
    		{
    			e1.m=e1.m-rule[i].m;
    			e1.c=e1.c-rule[i].c; 
    			e1.b=0;
    			if((e1.m>=e1.c||e1.m==0)&&((3-e1.m)>=(3-e1.c)||(3-e1.m)==0)&&e1.m<=3&&e1.c<=3&&e1.m>=0&&e1.c>=0)
    			{if(!cmp(&closed,e1))
    			if(!cmp(&open,e1))
    				EnQueue(&open,e1);}//须要解决元素问题
    		}//if
    		else //船在右岸,对数据库做加法
    		{e1.m=e1.m+rule[i].m;
    		e1.c=e1.c+rule[i].c;
    		e1.b=1;
    		if((e1.m>=e1.c||e1.m==0)&&((3-e1.m)>=(3-e1.c)||(3-e1.m)==0)&&e1.m<=3&&e1.c<=3&&e1.m>=0&&e1.c>=0)
    		{if(!cmp(&closed,e1))
    		if(!cmp(&open,e1))
    			EnQueue(&open,e1);}//须要解决元素反复问题
    		}//else
    		}//for
    	}//while
    	p=closed.front;//指向结果集
    	p=p->next;
    	printf("
    ");
    	while(p!=NULL){
    		printf("%d,%d,%d
    ",p->data.m,p->data.c,p->data.b);//打印解决结果
    		p=p->next;
    	}
    	getchar();//停顿函数
    } 
    


    实验结果:

  • 相关阅读:
    MySQL事务知识要点(一)
    MySQL 安全体系知识要点
    MySQL 安全性知识要点
    #翻译#通往SQL Server安全级别2的阶梯:身份验证; 唐•吉利; 原文链接:Stairway to SQL Server Security Level 2: Authentication http://www.sqlservercentral.com/articles/Stairway+Series/109975/
    SQL子查询&视图&更新&删除思维导图-误点难点(附示例代码)
    #翻译#通往t
    香港中文大学-人脸识别进展-2014-06
    NotesMITLinearAlgebra
    Notes Berkerly Statistics 2.1X Week4
    Notes on Brain Study
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/6719835.html
Copyright © 2020-2023  润新知