最近 地铁 上玩这个

微信一笔画游戏 的 路径算法

 

然后想了想  路径 算法 

只会穷举~

思路: 1.格子p出发 找下一步  找到 重复1  失败 2

             2,p下一步失败 重置p    p的上一步 q   把p 加入q的失败记录  以q出发 重新1

第一版

function findWay(m, n,/*空点 不能走*/emptyArrs,/*起点*/start) {
	let mn = new Array(m);

	console.time('a1')
	for (var i = 0; i < n; i++) {
		mn[i] = []
		for (var j = 0; j < m; j++) {
			mn[i][j] = {
				isEmpty: false,
				isPassed: false,
				lastStep: null,
				nextStep: null,
				failSteps: [],
				x: i,
				y: j,
				toNext() {
					let np = findNextStep([this.x, this.y])
					if (np) {
						return toNextStep([this.x, this.y], np)
					}
					else {
						if (checkEnd()) {
							return outPut();
						}
						else {
							return this.toFail();
						}
					}
				},
				toFail() {
					if (this.x == start[0] && this.y == start[1]) {
						return console.error('没有路')
					}

					let last = this.lastStep;
					if (!last) {
						return console.error('有错误')
					}

					inTotalPoint--;
					this.reset();
					last.failSteps.push([this.x, this.y])
					return last.toNext();
				},
				reset() {
					this.isPassed = false;
					this.failSteps = [];
					this.lastStep = null;
					this.nextStep = null;
				}
			}
		}
	}



	let totalPoint = m * n;
	let inTotalPoint = 1;

	emptyArrs.forEach(item => {
		mn[item[0]][item[1]].isEmpty = true;
		totalPoint--;
	})


	function findNextStep(point) {
		let p = mn[point[0]][point[1]];
		if (!p || p.isEmpty) {
			return false;
		}

		let ways = [-1, 0, 1]
		let failSteps = p.failSteps;

		for (var i = 0; i < 3; i++) {
			for (var j = 0; j < 3; j++) {
				let x = ways[i];
				let y = ways[j];
				if (x * x == y * y) {
					continue;
				}
				let pto = [point[0] + ways[i], point[1] + ways[j]]

				let np = getPoint(pto);
				if (!np) {
					continue;
				}

				if (np.isEmpty) {
					continue;
				}

				if (np.isPassed) {
					continue;
				}

				let isInFail = false;
				for (var c in failSteps) {
					if (failSteps[c][0] == pto[0] && failSteps[c][1] == pto[1]) {
						isInFail = true;
						break
					}
				}

				if (isInFail) {
					continue;
				}
				return pto;
			}
		}
		return false;
	}

	function getPoint(p) {
		return p && mn[p[0]] && mn[p[0]][p[1]]
	}

	let _count = 0
	function toNextStep(point0, point1) {
		let np0 = mn[point0[0]][point0[1]]
		let np1 = mn[point1[0]][point1[1]]

		np0.nextStep = np1;
		np1.lastStep = np0;
		np1.isPassed = true;
		inTotalPoint++;

		if (_count > 2200) {
			requestAnimationFrame(() => {
				np1.toNext();
			})
			_count = 0;
		}
		else {
			_count++;
			np1.toNext();
		}

	}

	function checkEnd() {
		return inTotalPoint == totalPoint
	}

	function outPut() {
		let p = mn[start[0]][start[1]];
		console.timeEnd('a1')
		while (p) {
			console.log(`i>${p.x},j${p.y}`)
			p = p.nextStep;
		}
	}

	mn[start[0]][start[1]].isPassed = true;
	mn[start[0]][start[1]].toNext();

}

额 耗时 有点久  就上图 用了 40 多 分钟

第二版 

 优化: 把 周围的点缓存 减少循环次数

function findWay2(m, n,/*空点 不能走*/emptyArrs,/*起点*/start) {
	let mn = new Array(m);

	console.time('a2')
	for (var i = 0; i < n; i++) {
		mn[i] = []
		for (var j = 0; j < m; j++) {
			mn[i][j] = {
				isEmpty: false,
				isPassed: false,
				lastStep: null,
				nextStep: null,
				arounds: [],
				failSteps: [],
				x: i,
				y: j,
				toNext() {
					let np = findNextStep([this.x, this.y])
					if (np) {
						return toNextStep([this.x, this.y], np)
					}
					else {
						if (checkEnd()) {
							return outPut();
						}
						else {
							return this.toFail();
						}
					}
				},
				toFail() {
					if (this.x == start[0] && this.y == start[1]) {
						return console.error('没有路')
					}

					let last = this.lastStep;
					if (!last) {
						return console.error('有错误')
					}

					inTotalPoint--;
					this.reset();
					last.failSteps.push([this.x, this.y])
					return last.toNext();
				},
				reset() {
					this.isPassed = false;
					this.failSteps = [];
					this.lastStep = null;
					this.nextStep = null;
				}
			}
		}
	}



	let totalPoint = m * n;
	let inTotalPoint = 1;

	emptyArrs.forEach(item => {
		mn[item[0]][item[1]].isEmpty = true;
		totalPoint--;
	})


	function findNextStep(point) {
		let p = mn[point[0]][point[1]];
		if (!p || p.isEmpty) {
			return false;
		}

		let ways = [-1, 0, 1]
		let failSteps = p.failSteps;

		let arounds = p.arounds;
		if (!arounds.length) {
			for (var i = 0; i < 3; i++) {
				for (var j = 0; j < 3; j++) {
					let x = ways[i];
					let y = ways[j];
					if (x * x == y * y) {
						continue;
					}
					let pto = [point[0] + ways[i], point[1] + ways[j]]

					let np = getPoint(pto);
					if (!np) {
						continue;
					}

					if (np.isEmpty) {
						continue;
					}
					arounds.push(pto)
				}
			}
		}

		for (var i in arounds) {
			let pto = arounds[i];

			let np = getPoint(pto);

			if (np.isPassed) {
				continue;
			}

			let isInFail = false;
			for (var c in failSteps) {
				if (failSteps[c][0] == pto[0] && failSteps[c][1] == pto[1]) {
					isInFail = true;
					break
				}
			}

			if (isInFail) {
				continue;
			}
			return pto;
		}
		return false;
	}

	function getPoint(p) {
		return p && mn[p[0]] && mn[p[0]][p[1]]
	}

	let _count = 0
	function toNextStep(point0, point1) {
		let np0 = mn[point0[0]][point0[1]]
		let np1 = mn[point1[0]][point1[1]]

		np0.nextStep = np1;
		np1.lastStep = np0;
		np1.isPassed = true;
		inTotalPoint++;

		if (_count > 2000) {
			requestAnimationFrame(() => {
				return np1.toNext();
			})
			_count = 0;
		}
		else {
			_count++;
			return np1.toNext();
		}

	}

	function checkEnd() {
		return inTotalPoint == totalPoint
	}

	function outPut() {
		let p = mn[start[0]][start[1]];
		console.timeEnd('a2')
		while (p) {
			console.log(`i>${p.x},j${p.y}`)
			p = p.nextStep;
		}
	}

	mn[start[0]][start[1]].isPassed = true;
	mn[start[0]][start[1]].toNext();

}

额 10分钟以内

第三版:

优化:

      把附近的 和 找下一步  去掉循环 (只能上下左右)

     直接带入点对象

function findWay3(m, n,/*空点 不能走*/emptyArrs,/*起点*/start) {
	let mn = new Array(m);

	console.time('a3')
	for (var i = 0; i < n; i++) {
		mn[i] = []
		for (var j = 0; j < m; j++) {
			mn[i][j] = {
				isEmpty: false,
				isPassed: false,
				lastStep: null,
				nextStep: null,
				arounds: [],
				failSteps: [],
				x: i,
				y: j,
				toNext() {
					let np = findNextStep(this)
					if (np) {
						return toNextStep(this, np)
					}
					else {
						if (checkEnd()) {
							return outPut();
						}
						else {
							return this.toFail();
						}
					}
				},
				toFail() {
					if (this.x == start[0] && this.y == start[1]) {
						return console.error('没有路')
					}

					let last = this.lastStep;
					if (!last) {
						return console.error('有错误')
					}

					inTotalPoint--;
					this.reset();
					last.failSteps.push(this)
					return last.toNext();
				},
				reset() {
					this.isPassed = false;
					this.failSteps = [];
					this.lastStep = null;
					this.nextStep = null;
				}
			}
		}
	}



	let totalPoint = m * n;
	let inTotalPoint = 1;

	emptyArrs.forEach(item => {
		mn[item[0]][item[1]].isEmpty = true;
		totalPoint--;
	})


	function findNextStep(p) {
		if (!p || p.isEmpty) {
			return false;
		}

		let ways = [-1, 0, 1]
		let failSteps = p.failSteps;

		let arounds = getArounds(p)

		return findStepIN(arounds, failSteps)
	}

	function getArounds(point) {
		let arounds = point.arounds;
		if (arounds.length) {
			return arounds;
		}



		let p = getPoint([point.x - 1, point.y]);
		if (p && !p.isEmpty) {
			arounds.push(p);
		}

		p = getPoint([point.x + 1, point.y]);
		if (p && !p.isEmpty) {
			arounds.push(p);
		}

		p = getPoint([point.x, point.y - 1]);
		if (p && !p.isEmpty) {
			arounds.push(p);
		}

		p = getPoint([point.x, point.y + 1]);
		if (p && !p.isEmpty) {
			arounds.push(p);
		}

		return arounds;
	}

	function findStepIN(arounds, failSteps) {
		let p0 = arounds[0];
		if (p0 && !p0.isPassed && isNotInFail(p0, failSteps)) {
			return p0;
		}

		p0 = arounds[1];
		if (!p0) {
			return null;
		}
		if (!p0.isPassed && isNotInFail(p0, failSteps)) {
			return p0;
		}

		p0 = arounds[2];
		if (!p0) {
			return null;
		}
		if (!p0.isPassed && isNotInFail(p0, failSteps)) {
			return p0;
		}

		p0 = arounds[3];
		if (!p0) {
			return null;
		}
		if (!p0.isPassed && isNotInFail(p0, failSteps)) {
			return p0;
		}
	}

	function isNotInFail(point, failSteps) {
		if (point == failSteps[0]) {
			return false;
		}
		if (failSteps[1] && point == failSteps[1]) {
			return false;
		}
		if (failSteps[2] && point == failSteps[2]) {
			return false;
		}
		if (failSteps[3] && point == failSteps[3]) {
			return false;
		}

		return true;
	}

	function getPoint(p) {
		return p && mn[p[0]] && mn[p[0]][p[1]]
	}

	let _count = 0
	function toNextStep(np0, np1) {

		np0.nextStep = np1;
		np1.lastStep = np0;
		np1.isPassed = true;
		inTotalPoint++;

		if (_count > 2500) {
			requestAnimationFrame(() => {
				return np1.toNext();
			})
			_count = 0;
		}
		else {
			_count++;
			return np1.toNext();
		}
	}

	function checkEnd() {
		return inTotalPoint == totalPoint
	}

	function outPut() {
		let p = mn[start[0]][start[1]];
		console.timeEnd('a3')
		while (p) {
			console.log(`i>${p.x},j${p.y}`)
			p = p.nextStep;
		}
	}

	mn[start[0]][start[1]].isPassed = true;
	mn[start[0]][start[1]].toNext();

}

又少一些了  3 分钟左右

第四版:

把周围点 按 度数 排序

function findWay4(m, n,/*空点 不能走*/emptyArrs,/*起点*/start) {
	let mn = new Array(m);
	let memCount = 2500

	console.time('a4')
	for (var i = 0; i < n; i++) {
		mn[i] = []
		for (var j = 0; j < m; j++) {
			mn[i][j] = {
				isEmpty: false,
				isPassed: false,
				lastStep: null,
				nextStep: null,
				arounds: [],
				failSteps: [],
				x: i,
				y: j,
				toNext() {
					let np = findNextStep(this)
					if (np) {
						return toNextStep(this, np)
					}
					else {
						if (checkEnd()) {
							return outPut();
						}
						else {
							return this.toFail();
						}
					}
				},
				toFail() {
					if (this.x == start[0] && this.y == start[1]) {
						return console.error('没有路')
					}

					let last = this.lastStep;
					if (!last) {
						return console.error('有错误')
					}

					inTotalPoint--;
					this.reset();
					last.failSteps.push(this)
					return last.toNext();
				},
				reset() {
					this.isPassed = false;
					this.failSteps = [];
					this.lastStep = null;
					this.nextStep = null;
				}
			}
		}
	}



	let totalPoint = m * n;
	let inTotalPoint = 1;

	emptyArrs.forEach(item => {
		mn[item[0]][item[1]].isEmpty = true;
		totalPoint--;
	})

	initArounds(getPoint(start));


	function findNextStep(p) {
		if (!p || p.isEmpty) {
			return false;
		}

		let ways = [-1, 0, 1]
		let failSteps = p.failSteps;

		let arounds = getArounds(p)

		return findStepIN(arounds, failSteps)
	}

	function initArounds(point) {
		if (point.arounds.length) {
			return;
		}
		point.arounds = getArounds(point);

		point.arounds.forEach(p => {
			initArounds(p)
		})

		point.arounds.sort((a, b) => a.arounds.length > b.arounds.length)
	}

	function getArounds(point) {
		// 结果 按度数排序
		let arounds = point.arounds;
		if (arounds.length) {
			return arounds;
		}

		let p = getPoint([point.x - 1, point.y]);
		if (p && !p.isEmpty) {
			arounds.push(p);
		}

		p = getPoint([point.x + 1, point.y]);
		if (p && !p.isEmpty) {
			arounds.push(p);
		}

		p = getPoint([point.x, point.y - 1]);
		if (p && !p.isEmpty) {
			arounds.push(p);
		}

		p = getPoint([point.x, point.y + 1]);
		if (p && !p.isEmpty) {
			arounds.push(p);
		}

		return arounds;
	}

	function findStepIN(arounds, failSteps) {
		let p0 = arounds[0];
		if (p0 && !p0.isPassed && isNotInFail(p0, failSteps)) {
			return p0;
		}

		p0 = arounds[1];
		if (!p0) {
			return null;
		}
		if (!p0.isPassed && isNotInFail(p0, failSteps)) {
			return p0;
		}

		p0 = arounds[2];
		if (!p0) {
			return null;
		}
		if (!p0.isPassed && isNotInFail(p0, failSteps)) {
			return p0;
		}

		p0 = arounds[3];
		if (!p0) {
			return null;
		}
		if (!p0.isPassed && isNotInFail(p0, failSteps)) {
			return p0;
		}
	}

	function isNotInFail(point, failSteps) {
		if (point == failSteps[0]) {
			return false;
		}
		if (failSteps[1] && point == failSteps[1]) {
			return false;
		}
		if (failSteps[2] && point == failSteps[2]) {
			return false;
		}
		if (failSteps[3] && point == failSteps[3]) {
			return false;
		}

		return true;
	}

	function getPoint(p) {
		return p && mn[p[0]] && mn[p[0]][p[1]]
	}

	let _count = 0
	function toNextStep(np0, np1) {

		np0.nextStep = np1;
		np1.lastStep = np0;
		np1.isPassed = true;
		inTotalPoint++;

		if (_count > memCount) {
			requestAnimationFrame(() => {
				return np1.toNext();
			})
			_count = 0;
		}
		else {
			_count++;
			np1.toNext();
		}
	}

	function checkEnd() {
		return inTotalPoint == totalPoint
	}

	function outPut() {
		let p = mn[start[0]][start[1]];
		console.timeEnd('a4')
		while (p) {
			console.log(`i>${p.x},j${p.y}`)
			p = p.nextStep;
		}
	}

	mn[start[0]][start[1]].isPassed = true;
	mn[start[0]][start[1]].toNext();

} 

30s 内

没有方向了 

 

第五版:

优化:使用worker 第一步的 三个方向 开启3个worker

function findWay5(m, n,/*空点 不能走*/emptyArrs,/*起点*/start) {
	console.time("a5")
	//当起点的

	startWorker([-1, 0])
	startWorker([1, 0])
	startWorker([0, 1])
	startWorker([0, -1])


	function startWorker(direction) {
		var work = new Worker('./FindWayWorker.js')
		var data = [m, n, emptyArrs, start, direction];
		work.postMessage(JSON.stringify(data))
		work.onmessage = e => {
			console.timeEnd("a5")
			console.log(e.data);
		}
		work.onerror = e => {
			console.error(e.message)
		}
	}
}

20 秒 左右   没有 本质 提升

 

在减少  估计 只能 改算法了   无力了~~

相关文章:

  • 2022-12-23
  • 2021-12-17
  • 2021-05-23
  • 2021-10-01
  • 2022-12-23
  • 2021-09-28
  • 2021-11-01
  • 2021-12-20
猜你喜欢
  • 2022-12-23
  • 2022-01-11
  • 2021-06-23
  • 2021-04-07
  • 2021-06-26
  • 2021-07-06
相关资源
相似解决方案