回溯法,因为树的规模会很庞大,所以要在dfs中加入提前退出条件,当找到组合方法后,后面的所有枝全部剪掉。每一次dfs的优先关系为先7后5后3,这样第一个找到的组合方法使用的箱子数目最少。因为在找到第一个组合之前,回溯的关系保持,在找到第一个组合之后,也不再需要回溯了。
#include
#include
using namespace std;
void dfs(vector& temp,int target,int val);//回溯法
vector> res;//保存组合方法
bool flag=true;//是否已找到方法
int main()
{
int target;
cin>>target;
vector temp;//方法暂存变量
dfs(temp,target,7);//先7
dfs(temp,target,5);//后5
dfs(temp,target,3);//后3
if(res.empty())
cout<
else
cout<
return 0;
}
void dfs(vector& temp,int target,int val)
{
temp.push_back(val);//当前选取的货物放入方法暂存
if(target==val)//箱子装满
{
res.push_back(temp);//当前方法放入结果
flag=false;//已找到方法
}
//不是3选1 而是优先级 7>5>3 否则正确组合可能被跳过
if(target-val>=7&&flag)//当前剩余值大于等于7
dfs(temp,target-val,7);//先放7
if(target-val>=5&&flag)//当前剩余值大于等于5
dfs(temp,target-val,5);//再放置5
if(target-val>=3&&flag)//当前剩余值大于等于3
dfs(temp,target-val,3);//再放置3
temp.pop_back();//尾回溯 删除本轮添加的货物
} DP解法。dp[i]代表装满重量为i的箱子所需的最少货物数目,那么dp[i]=min(dp[i-3],dp[i-5],dp[i-7])+1。初始化并模拟递推过程即可。使用INT_MAX代表不能被装满。 #include
#include
#include// for INT_MAX
using namespace std;
int main()
{
int target;
cin>>target;
vector dp(target+1,INT_MAX);//dp[i] 装满体积为i的箱子所需最少货物数目
dp[3]=1;
dp[5]=1;
dp[7]=1;
dp[6]=2;//初始化
for(int i=8;i<=target;i++)//递推过程
{
int a=dp[i-3],b=dp[i-5],c=dp[i-7];//a b c分别代表i-3 i-5 i-7再装一个货物
if(a==INT_MAX&&b==INT_MAX&&c==INT_MAX)
dp[i]=INT_MAX;//表示i不能被被装满
else
dp[i]=min(min(a,b),c)+1;//最少的货物数目+1
}
if(dp[target]==INT_MAX)
cout<
else
cout<
return 0;
}