让你的搜索变得精致——启发式搜索

文章介绍了启发式搜索的概念,并通过一个背包问题的实例详细解释了如何构建估价函数来优化搜索过程。示例中使用深度优先搜索(DFS)配合估价函数求解最大价值。此外,文中提到A*算法也是启发式搜索的一个经典应用,但并未在本文展开讨论。
摘要由CSDN通过智能技术生成

世上最可怕的事就是比你聪明的人,比你还努力还认真。

序言:启发式搜索是一种引用广泛的搜索技巧,它通过构造一个估价函数在搜索前或搜索中途就发现某种搜索不符合题意,因此可以直接回溯或进入下一层搜索。启发式搜索的思想比较抽象,我们用例题的方式介绍。

例1:采药

有N种物品和一个容量为W的背包,每种物品有重量wi和价值vi两种属性,要求选若干个物品(每种物品只能选一次)放入背包,使背包中物品的总价值最大,且背包中物品的总重量不超过背包的容量。

解析

不难看出,启发式搜索的重点就是如何写估价函数。在这道题当中,我们很容易看出的两个标准,即容量与价值。即

  1. 当超过了容量时,解不成立(容量)
  2. 舍弃某个物品后,如果剩余所有未取物品的价值和背包中物品价值的和小于当前的最大解,则解不成立(价值)

代码

估价函数,有了上面的解析,自己过一遍就能明白。每个变量的意义可以看下面的完整代码

int f(int i)
{
	int sum_vol;
	for (int i = 0; i < n; i++) {
		if (book[i] == 1)sum_vol += s_val[i];
	}
	if (sum_vol > w)return 0;
	int max_val=0;
	for (int j = 0; j < i; j++) {
		if (book[j] == 1)max_val += s_val[j];
	}
	for (int j = i; j < n; j++) {
		max_val += s_val[j];
	}
	if (max_val <= ans)return 0;
}

完整代码

#include<iostream>
#include<algorithm>
using namespace std;
int* book;//在当前搜索情况中是否取了这个物品
int* s_val;//单个物品的价值
int* s_vol;//单个物品的体积
int n;//物品种数
int w;//背包体积
int ans = 0;//存储最大价值解的变量
int now_val;//存储在当前搜索情况中的总价值
int* ans_book;//存储取最大价值时的取法
void ini()
{
	scanf("%d %d", &n, &w);
	book = (int*)malloc(sizeof(int) * n);
	memset(book, 0, sizeof(int) * n);
	ans_book = (int*)malloc(sizeof(int) * n);
	memset(ans_book, 0, sizeof(int) * n);
	s_val = (int*)malloc(sizeof(int) * n);
	s_vol = (int*)malloc(sizeof(int) * n);
	for (int i = 0; i < n; i++) {
		scanf("%d %d", &s_val[i], &s_vol[i]);
	}
}
int f(int i)
{
	int sum_vol;
	for (int i = 0; i < n; i++) {
		if (book[i] == 1)sum_vol += s_val[i];
	}
	if (sum_vol > w)return 0;
	int max_val=0;
	for (int j = 0; j < i; j++) {
		if (book[j] == 1)max_val += s_val[j];
	}
	for (int j = i; j < n; j++) {
		max_val += s_val[j];
	}
	if (max_val <= ans)return 0;
}
void dfs(int i)
{
	if (i == n)return;
	if (now_val > ans) {
		ans = now_val;
		for (int i = 0; i < n; i++)ans_book[i] = book[i];
	}
	else {
		book[i] = 1;
		now_val += s_val[i];
		if (f(i))dfs(i + 1);
		book[i] = 0;
		now_val -= s_val[i];
	}
}
int main(void)
{
	ini();
	dfs(0);
	printf("%d\n", ans);
	for (int i = 0; i, n; i++) {
		printf("%d", ans_book[i]);
	}
}

由此可见,当写出估价函数之后,剩下的就只是普通的dfs了。
还有另一种非常经典的算法,即A*算法也使用了启发式搜索的思想,由于这个算法比较复杂,我将单独开一篇文章讲述这种算法。

都看到这里啦,觉得还不错的同学点赞关注支持一下吧,万分感谢!!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霜_哀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值