golang实现商人渡河问题(暴力解法)

学习需要,结合模型实现了商人过河问题。

包括:

  1. N商人N随从 M小船问题
  2. 人,猫,鸡,米过河问题

目前使用暴力算法,后期打算写下Dijstra算法求解(毕竟暴力算法无法证明无解性)

模型

S允许状态集合

D允许决策集合

代码

N对商人随从过河
const N = 3

// 遍历算法
// 输入 商人 随从人数 n = 3,4,5...
// 输出 每一步的 决策
func nextStep(x, y, stepCount int, printContent string) {
    // 设置递归层数,防止无限递归。
	if stepCount > 30 {
		return
	}
	// 决策集合
	for _, decision := range [][2]int{{0, 1}, {0, 2}, {1, 0}, {1, 1}, {2, 0}} {  // 可以改变允许决策集合D
		nextX, nextY := decide(x, y, decision[0], decision[1], stepCount)
		if checkInS(nextX, nextY) {
			nextPrintContent := printContent + fmt.Sprintf("第%d步:%d,%d.", stepCount, decision[0], decision[1])
			//fmt.Println(nextPrintContent)
			if nextX == 0 && nextY == 0 {
				fmt.Println(nextPrintContent, nextX, nextY)
				return
			}
			nextStep(nextX, nextY, stepCount+1, nextPrintContent)
		}
	}

}

// 做决策
func decide(x, y, decisionOne, decisionTwo, stepCount int) (int, int) {
	if stepCount%2 != 0 {
		return x - decisionOne, y - decisionTwo
	} else {
		return x + decisionOne, y + decisionTwo
	}
}

// 查看现在的状态是否符合 S 允许状态集合
func checkInS(x, y int) bool {
	if N <= 0 {
		return false
	}
	if x == y {
		return true
	}

	for j := 0; j <= N; j++ {
		if x == 0 && y == j {
			return true
		}
	}

	for j := 0; j <= N; j++ {
		if x == N && y == j {
			return true
		}
	}

	return false
}

复制代码
人猫鸡米过河

同上面算法类似,只是增加了变元

func nextStep(a, b, c, d, stepCount int, printContent string) {
	if stepCount > 7 {
		return
	}
	for _, decision := range [][4]int{{1, 0, 0, 0}, {1, 0, 0, 1}, {1, 0, 1, 0}, {1, 1, 0, 0}} {
		nextA, nextB, nextC, nextD := decide(a, b, c, d, decision[0], decision[1], decision[2], decision[3], stepCount)
		if checkInS(nextA, nextB, nextC, nextD) {
			nextPrintContent := printContent + fmt.Sprintf("第%d步:%d,%d,%d,%d.", stepCount, decision[0], decision[1], decision[2], decision[3])
			//fmt.Println(nextPrintContent)
			if nextA == 0 && nextB == 0 && nextC == 0 && nextD == 0 {
				fmt.Println(nextPrintContent, nextA, nextB, nextC, nextD)
				return
			}
			nextStep(nextA, nextB, nextC, nextD, stepCount+1, nextPrintContent)
		}
	}
}

func decide(a, b, c, d, decideOne, decideTwo, decideThree, decideFour, stepCount int) (int, int, int, int) {
	if stepCount%2 != 0 {
		// 是奇数 ,减
		return a - decideOne, b - decideTwo, c - decideThree, d - decideFour
	}
	return a + decideOne, b + decideTwo, c + decideThree, d + decideFour
}

func checkInS(a, b, c, d int) bool {
	if 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1 && 0 <= d && d <= 1 {
		if a == 0 {
			if b+c == 2 || c+d == 2 {
				return false
			}
			return true
		}
		if a == 1 {
			if b+c == 0 || c+d == 0 {
				return false
			}
			return true
		}
		return true
	}
	return false
}

复制代码
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值