不碰南墙不回头。
常用于给定一个序列,枚举子序列选择满足某个特征的最优子序列
- 有n见物品,给出重量和价值,在不超过容量V的前提下求最大价值
#include<cstdio>
int n,v,max = 0; //物品件数,背包容量,最大价值
int w[10],c[10];//重量,价值
void DFS(int index,int sumW,int sumC){
if(index == n){
if(sumW < v && sumC > max){
max = sumC;
}
return;
}
DFS(index+1,sumW,sumC); //不选下一件物品
DFS(index+1,sumW+w[index],sumC+c[index]); //选择下一数据
}
//剪枝
void DFS2(int index,int sumW,int sumC){
if(index == n){
return;
}
DFS(index+1,sumW,sumC); //不选下一件物品
if(sumW+w[index] <= v){
if(sumC + c[index] >max){
max = sumC+c[index];
}
DFS(index+1,sumW+w[index],sumC+c[index]); //选择下一数据
}
}
//测试数据
//5 8
//3 4 1 2 2
//4 5 2 1 3
//10
//DFS 解决问题的核心,给定一个序列,枚举这个序列的所有子序列(不一定连续),寻找最优解
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]);
}
DFS2(0,0,0); //初始状态
printf("%d\n",max);
}
- 从n个整数中选取k个数,在和为x的条件下,求序列最大的平方和。
如果需要保存路径,需要使用vector
。
#include <cstdio>
#include <vector>
using namespace std;
int n = 4,k = 2,x = 6,Max = 0; //n个整数,选k个数,和为x
int arr[] = {2,3,3,4};//n个整数
vector<int> temp;
vector<int> ans;
void DFS(int index,int sumK,int sumX,int sumSq) {
if(sumK == k && sumX == x){
if(sumSq > Max){
Max = sumSq;
ans = temp;
}
}
if(index == n || sumK > k || sumX >x) return;
DFS(index+1,sumK,sumX,sumSq);
temp.push_back(arr[index]);
DFS(index+1,sumK+1,sumX+arr[index],sumSq+arr[index]*arr[index]);
temp.pop_back();
}
int main(){
DFS(0,0,0,0);
printf("%d\n",Max);
for(int i : ans){
printf("%d ",i);
}
}