记忆化搜索(3):P1433 吃奶酪——求最大最小值常用的dfs剪枝方法

记忆化搜索(3):P1433 吃奶酪——求最大最小值常用的dfs剪枝方法_第1张图片

输入输出样例
输入 #1复制
4
1 1
1 -1
-1 1
-1 -1
输出 #1复制
7.41

总结目录

1 本题搜索思路
2 本题剪枝思路

1 本题搜索思路

这题搜索就是典型的dfs搜索,并且使用回溯记录哪些点是访问过的。在求距离的时候需要知道当前在第几个点,这样才能继续往下求距离。当全部点访问完之后,就“走到尽头”了,此时比较一下当前的sum和minres的大小就可以知道哪个是最小值了。minres初始化为一个很大的数,这里使用了int_max

2 求最大最小值的dfs剪枝思路

以上的算法显然暴力dfs会TLE,因此要考虑加速的方法。加速的话一个是记忆化搜索。一个是使用剪枝。记忆化搜索的话最好是用在结果不会更新的情况,即算出来之后,后面的计算都是可以用这个结果的。这样会比较好,但是这题里面好像不太合适。 其实这里也可以用一点点,就是去记忆化两条边之间的距离,这样就不用dist2p函数来计算了,但是这样其实加速得不多。

这题实际上用剪枝其实更明显。因为要求最大最小值,所以在计算过程中一定是不断地递增的。所以我们只需要在num如果还没有到底已经超过了minres那么也就没有必要进行后续的搜索了。这个剪枝方法在求最大最小值的题目中被常常用到。

代码

#include
#include
#include
#include
using namespace std;
#define maxsize 20
int used[maxsize];//记录访问过的点数
double minres = INT_MAX;
int n;

struct Point {
	double x;
	double y;
};
Point points[maxsize];


double dist2p(Point a, Point b) {
	//计算两点之间距离
	return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

void dfs(int num,int curpos,double sum) {
	//num表示已经访问过的点的数量
	if (num=minres) {
		return;//剪枝
	}
	if (num >= n) {
		minres = min(sum, minres);
		return;
	}

	for (int i = 1; i <= n; i++) {
		if (used[i] != 1) {
			used[i] = 1;
			double dst = dist2p(points[curpos], points[i]);
			dfs(num + 1, i, sum + dst);
			used[i] = 0;
		}
	}
}



int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> points[i].x >> points[i].y;
	}
	points[0].x = 0;
	points[0].y = 0;
	dfs(0,0,0);
	printf("%.2f", minres);
	return 0;
}

你可能感兴趣的:(记忆化搜索)