我是靠谱客的博主 无限小蝴蝶,最近开发中收集的这篇文章主要介绍POJ2248 Addition Chains(迭代加深搜索)题目链接: poj2248题目大意解题思路实现代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目链接: poj2248

题目大意

给你一个数字n,你需要构造一个首项为1,末项为n的递增序列,并且这个序列的非首项的数字都能从它前面找到两项之和与之相等,前面的两项可以为同一项,即可重复,并且要让这个序列尽可能短,如果有多解输出其中一种序列解即可。(n<=100)

解题思路

朴素搜索

  1. 我们可以从第二项开始构造。因为已知第一项为1,所以通过前面的已知项生成的后续项一定能保证上述的『 x [ i ] + x [ j ] = x [ k ] x[i] + x[j] = x[k] x[i]+x[j]=x[k]』的条件;
  2. 在生成后续项的同时不断和当前已有序列的最后一项比较即可保证『序列递增』的条件;
  3. 而『末项为n』的条件可以在递归的终点去检查一下

此时,我们发现这种搜索方式没有一个准确的搜索终点,或者按d=1的等差数列去考虑则搜索树有可能100层,如果按朴素的dfs去搜索解,显然效率低下,不可取。

我们大致考虑下二进制序列:『1、2、4、8、16、32、64、128』显然符合我们上面要寻找的序列的部分条件,并且长度较少。我们可以大致判定解序列的长度也不会太长,也就是说,搜索树的规模(层数)可以大幅度减少。

此时,我们考虑bfs去搜索解,显然效率以及序列最短的条件都可以达到。但就结果而言,bfs不利于剪枝优化,并且空间复杂度较高,所以采取这种方式。

迭代加深

它能解决搜索树规模未知或者十分庞大,但解的规模比较小的搜索优化。避免我们在非答案的分支上花太多的时间。大致思想是:人为地给一次深度优先搜索中加入一个层数限制,这样就便于较浅的搜索分支地快速转移,等到这种限制的搜索结果中没有我们的答案再进一步扩展搜索层数。虽然可能会造成前几层重复搜索,但显然这些冗余搜索的时间远小于遍历整个搜索树的时间。 总而言之,这种搜索方式以前几层重复搜索的代价,换取让层数较小的所有子树先得到遍历,并且还不用存子树的状态,节约了空间复杂度。

就理解而言,这是一种基于深度优先广度优先,并且较为折中的搜索方式。

回到题目,我们可以把序列的长度作为搜索树的深度,从 2 − n 2 - n 2n开始迭代,当某个深度能够找到解后就退出直接输出答案。每层的搜索中,我们可以以 O ( d e e p t h 2 ) O(deepth^2) O(deepth2)的时间去枚举下一个计算下一层需要填上的数字,当发现计算到最后一层,末项为n,则答案找到。

优化1,去重。如果『x + y』的结果之前已经算过了,此时还能继续搜索说明这个答案无效,那么显然没必要搜索这个的子树,check,开一个vis标记即可。

优化2,两个数字相加大于n,显然不符题意,check。

优化3,由于序列是递增的,所以我们在计算下一项数字时用较大的先算能使得我们搜索的分支更快地到达n地界限,那么就会减少相加比较小地数字地无用搜索。 比如我们要计算的终点是4,此时有『1、2』的序列,那么我们让「2+2」先于「1+1」计算,能一次就找到答案而不用在搜完「1+1」、「1+2」…后才得到答案。总而言之就是拉大每次搜索的步长,之后在慢慢微调,和倍增的思想很类似。

实现代码

#include <iostream>
#include <cstring>
using namespace std;

int n, arr[105];

bool dfs(int u, int dep) {
	if (u == dep) return arr[u - 1] == n; //到达下界 判断该分支的正确性
	bool vis[105] = {false};
	//保证arr[u]等于arr[i]+arr[j]
	for (int i = u - 1; i >= 0; i--) {
		for (int j = i; j >= 0; j--) {
			int s = arr[i] + arr[j];
			if (s > n || vis[s] || s <= arr[u - 1]) continue;
			arr[u] = s; vis[s] = true;
			if (dfs(u + 1, dep)) return true;
		}
	}
	return false;
}

int main() {

	while (cin >> n, n) {
		arr[0] = 1;
		//迭代加深
		for (int i = 1; i <= n; i++) {
			if (dfs(1, i)) {
				for (int j = 0; j < i; j++) {
					cout << arr[j] <<  " n"[j == i - 1];
				}
				break;
			}
		}
	}
	return 0;
}

最后

以上就是无限小蝴蝶为你收集整理的POJ2248 Addition Chains(迭代加深搜索)题目链接: poj2248题目大意解题思路实现代码的全部内容,希望文章能够帮你解决POJ2248 Addition Chains(迭代加深搜索)题目链接: poj2248题目大意解题思路实现代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部