①输出最优值:
简单,用个best比较更新,最后一步函数return;即可
②判断是否到达:
由于要return true/false,但只能返回的是最后一个函数的真假,而我们需要的是第一个函数返回值的真假,需要加几句判断来return
③输出路径:
vis数组,容易
#include<bits/stdc++.h>
using namespace std;
int n,m,r,best;//r为剩余量
bool vis[3005];
bool cnt[3005];
int a[3005];
bool Backtrack(int i,int cur)
{
if(i>=n)
{
if(cur==m)
{
for(int i=0;i<n;i++)cnt[i]=vis[i];
best=cur;
return true;//这里return 的是参数为n,要想使参数为0的原函数返回true,还需要一番功夫
}
else
return false;
}
r-=a[i];
if(cur+a[i]<=m) //限界函数
{
cur+=a[i];
vis[i]=true;
if(!Backtrack(i+1,cur))//满足限定条件,到最后发现不能取,回溯时
{
cur-=a[i];
}
else
return true;
}
if(cur+r>best)//剪枝函数
{
vis[i]=false;//此句可移到cur-=a[i]后
if(Backtrack(i+1,cur))return true;//不满足限界条件,继续下一个,不可省略
}
r+=a[i];
return false;//都不满足,不可省略
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>a[i];
r+=a[i];
}
if(Backtrack(0,0))
{
for(int i=0;i<n;i++)
if(cnt[i])cout<<a[i]<<" ";
}
else
cout<<"No Solution!"<<endl;
}