商人过河问题

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

商人过河问题

/***************************************************

*M个商人与每人各带的一个仆人过河问题

*船每次至多运N个人,至少要有一人划船

*在任一岸,当商人数<仆人数时,仆人就杀人越货

*过河由商人安排运送人员及数目

*找出安全渡河的全部方法并打印(原问题中M=3,N=2)

*2010-10-10 20时许(纪念伟大的双十)

* LYP

***************************************************/

/******************************************************************

*本题为多步决策

*若考虑只针对人数为 M = 3 对,每次过河人数最多 N = 2

*可以证明路径中必须经坐标中(3,1)过至(1,1)点(过诃时),

*后返回至(2,2)点,再过诃至(0,2)点(只剩2个仆人)

*可以先考虑(3,3)到(3,1)点

*再经(0,2)至(0,0),完成过诃(由图形的对称性关系,可以直接将(3,1)至(3,1)路径翻转,更改对应标号即可)

*当然也可以用动态规划求解

*本代码不限定M,N值,可通过修改宏M,N的值,求其他商人(仆人)数与最大过河人数的全部路径

*******************************************************************/

/********************************************************************* *

*商人数x < 仆人数y时遭杀人越货,过河失败

*对应可行域为:

*x = 0, y = 0…M; elements[]中编号0…M

*0 < x < M, y = x; elements[]中编号M+1…2M-1

*x = M, y = 0…M; elements[]中编号2M…3M

*图像上表示如下:(共 3*M+1 个点),过河即从3M点到0点

*过河为左下方1/4圆区域

*返回为右上方1/4圆区域

*点成中心对称分布,对称的点过河、返回时点的分布情况互为相同

/\ y:仆人

|

| 编号:

M* * M\ \3M

| | .

* * * .

* * * 2\M+2\2M+2

* * * 1\M+1\2M+1

-*------------------*--------> 0\ \2M

|0 M x:商人

|

*

*********************************************************************/

#include

#include

#include

#define M 3

/* M为商人仆人对数*/

#define N 2

/* N为渡河时船的最大容量*/

#define STACK_Vol 30

/* 栈的容量*/

#define DEBUG 0

/* 调试时用的宏,用于查看unit中可到达的各点编号*/

enum status{ NO, YES};

/* 标记elements中的go_flag(back_flag)*/

/* 以NO=0标记过河(返回)时没到过该点,YES=1标记过河(返回)到过该点*/

struct Element{

int* go; /* 存储过河时可以到达的点的动态空间指针,以-1标记结束*/

int* back; /* 存储返回时可以到达的点的动态空间指针,以-1标记结束*/

enum status go_flag; /* 以NO=0标记为未曾从该点过河,YES=1为曾从该点过河*/

enum status back_flag; /* 以NO=0标记为未曾从该点返回,YES=1为曾从该点返回*/

}elements[3 * M + 1];

/*********************************************************************** ******************

*对可行域的点对行编号,全局变量,已被自动初始化为NULL和0

*考虑到N一般较小,每点到达的点也较少,所以进行初始化并存储在动态分配的空间中

*只考虑较小的N,对较大的N( >= 4),解题为平凡的,程序空间时间复杂度较大,不用本程序求解

*********************************************************************** *****************/

struct Stack{

int array[ STACK_Vol + 1]; /* 存储经过的路径,注意:最多为30步*/

int mark[ STACK_Vol + 1]; /* 存储经过对应点的链表中下次要走的元素标号*/ int top; /* 栈顶指针,指向使用的空间*/

}stack;

/**************************

* 找出路径要用到的运算栈*

**************************/

int path_ok; /* 记录找到路径数量*/

int up_bound = 3 * M; /* 数组中最大点的下标(上界*/

void unit( void); /* 初始化各点的可到达的点*/

void path( void); /* 找出无环路的过河路径*/

void print_path( int *); /* 打印出过河的路径*/

void delete_link( void); /* 释放动态分配的内存*/

int main()

{

相关文档
最新文档