商人过河问题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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()
{