《算法笔记》8.1 深度优先搜索

一.深度优先搜索
枚举所有完整路径以遍历所有情况;
实现方式:递归 / 非递归;
示例一:
在这里插入图片描述

void DFS(int index, int sumW, int sumC) {
	//终点:
	if(index == n) return; 
	//不选第 index 件物品:
	DFS(index + 1, sumW, sumC);
	//选第 index 件物品:
	if(w[index] + sumW <= V) {
		if(sumC + c[index] > ans) ans = sumC + c[index];
		DFS(index + 1, sumW + w[index], sumC + c[index]);
	}
}

示例二:
(1).
在这里插入图片描述

void DFS(int index, int nowK, int sum, int sumSqu) {
	//有效终点:
	if(nowK == K && sum == X) {
		if(sumSqu > Squ) {
			Squ = sumSqu;
			ans = temp;
		}
		return;
	}
	//无效终点:
	if(index == n || nowK > K || sum > X) return;
	//选第 index 个数:
	temp.push_back(s[index]);
	DFS(index + 1, nowK + 1, sum + s[index], sumSqu + s[index] * s[index]);
	temp.pop_back();
	//不选第 index 个数:
	DFS(index + 1, nowK, sum, sumSqu);
}

注意:
1).选第 index 个数时,先把 s[index] 放进 temp 里,进入“选 s[index] ”这条分支;当这条分支结束时,把 s[index] 从 temp 中拿出来,使它不会影响“不选 s[index] ”这条分支;
2).两个岔路位置不可以颠倒,为什么?

(2).
假设题目中的 N 个整数均可以被选择多次,则将DFS(index + 1, nowK + 1, sum + s[index], sumSqu + s[index] * s[index]);替换成DFS(index, nowK + 1, sum + s[index], sumSqu + s[index] * s[index]);即可;

二.题目
1.PAT A1103
思路:
和示例二(2)一样;

注意:
1).保证底数字典序最大:让 index 从小到大遍历;
2).不能从 N 开始遍历,会超时;必须从 n ^ P <= N 的数处开始(比如169 5 2,index = 13);计算 n 的方法不能是 pow(N, 1 / P),因为 1 / P 会是0;

代码:

#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
const int maxn = 420;
int N, K, P;
vector<int> ans;
vector<int> temp;
int maxSumFac = 0;
void DFS(int index, int nowK, int sum, int sumFac) {
	if(nowK == K && sum == N) {
		if(sumFac > maxSumFac) {
			maxSumFac = sumFac;
			ans = temp;
		}
		return;
	}
	if(sum > N || nowK > K || index - 1 < 0) return;
	temp.push_back(index);
	DFS(index, nowK + 1, sum + pow(index, P), sumFac + index);
	temp.pop_back();
	DFS(index - 1, nowK, sum, sumFac);

}
int main() {
	scanf("%d%d%d", &N, &K, &P);
	int n;
	for(n = 1; n <= N; n++) {
		if(pow(n, P) > N) break;
	}
	n = n - 1;
	DFS(n, 0, 0, 0);
	if(ans.size() == 0) printf("Impossible\n");
	else {
		printf("%d = ", N);
		for(int i = 0; i < ans.size(); i++) {
			if(i == ans.size() - 1) printf("%d^%d\n", ans[ans.size() - 1], P);
			else printf("%d^%d + ", ans[i], P);
		}
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值