深度优先遍历(DFS)
是什么?
深度优先搜索是一种枚举所有完整路径以遍历所有情况的搜索方法。使用递归可以很好的实现深度优先遍历,因此,只能说递归是实现深度优先遍历的一种实现方式。
解决问题
给定一个序列,枚举这个序列所有的子序列
例如{1,2,3}子序列包含{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}
选择最优子序列,使它的某个特征是所有子序列中最优的。
这个问题也就是从n个整数中,选择k个数的所有方案。
应用一
N件物品,重量w[i],价值c[i],选出若干,使总重量不超过V,找出价值最大的值
思路
使用DFS遍历判断
结束条件,所有的可能序列遍历一遍
岔路口分支:选择当前物品,或者不选择当前物品。
代码
#include<stdio.h>
const int maxn = 20;
int w[maxn],c[maxn];
int n,V;
int maxc = 0;
void DFS(int index,int sumW,int sumC){
if(index == n){
if(sumW <= V && sumC > maxc){
maxc = sumC;
}
return ;//即使不是最大的maxc也要return 出去
}
DFS(index + 1 ,sumW,sumC);
DFS(index + 1 ,sumW+w[index],sumC+c[index]) ;//注意下标的差1
}
int main() {
scanf("%d %d",&n,&V);
for(int i = 0; i<n; i++) {
scanf("%d",w+i);
}
for(int i = 0; i<n; i++) {
scanf("%d",c+i);
}
DFS(0,0,0);
printf("%d\n",maxc);
return 0;
}
改进(剪枝)
原先直接加入当前物品,也不管不顾是否已经超出了总重量,
现在在加入之前,提前加入判断条件
#include<stdio.h>
const int maxn = 20;
int w[maxn],c[maxn];
int n,V;
int maxc = 0;
void DFS(int index,int sumW,int sumC) {
if(index == n) {
return ;//即使不是最大的maxc也要return 出去
}
DFS(index + 1 ,sumW,sumC);
if(sumW+w[index] <= V) {
if(sumC+c[index]>maxc)
maxc = sumC+c[index];
DFS(index + 1 ,sumW+w[index],sumC+c[index]) ;//注意下标的差1
}
}
int main() {
scanf("%d %d",&n,&V);
for(int i = 0; i<n; i++) {
scanf("%d",w+i);
}
for(int i = 0; i<n; i++) {
scanf("%d",c+i);
}
DFS(0,0,0);
printf("%d\n",maxc);
return 0;
}
应用二
N个整数中选择k个数,使得整数和恰好等于给定的整数x,如果有多种方案,选择平方和最大。
这里加入了如何存储最优方案,先用一个temp用来存放该过程的一个序列,如果是当前最优,则交给ans
#include<stdio.h>
#include<vector>
using namespace std;
const int maxn = 20;
int w[maxn];
int n,k,x;
int maxseq = 0;
vector<int> temp,ans;
void DFS(int index,int nowk,int sum,int sumseq) {//存放当前位置,当前包含的数量,当前和数,平方和数
if(nowk == k&&sum == x)
{
if(sumseq > maxseq ){
maxseq = sumseq;
ans = temp;
}
return ;//即使不是最大的maxc也要return 出去
}
if(index == n||nowk> k ||sum > x){
return;
}
//选择当前的
temp.push_back(w[index]);
DFS(index + 1 ,nowk + 1,sum +w [index],sumseq + w[index] * w[index]);
temp.pop_back();
DFS(index + 1 ,nowk ,sum ,sumseq) ;//不选择
}
int main() {
scanf("%d %d %d",&n,&k,&x);//n个数选择k个使和为x
for(int i = 0; i<n; i++) {
scanf("%d",w+i);//输入n个数
}
DFS(0,0,0,0);
for(auto it = ans.begin();it!=ans.end();it++){
printf("%d ",*it);
}
printf("\n");
printf("%d\n",maxseq);
return 0;
}