要尽可能减少花费-->递归的分支尽可能少-->优先考虑放重猫
优先考虑放重猫,需要从大到小排个序,
一直往下搜索,答案是唯一的。
放得下猫就继续往该车往下加
放不下就再另外开一辆放猫
分两个分支去放
开一辆继续放其他猫的为一个分支
开另一辆单独只放一只猫的为另一个分支
接下来递归调用处理,对于每个分支递归后有又n
个分支,一直递归下去,直至递归到n
层。说明当前的车数为最优解。
我们可以建立如下递归搜索图:
递归DFS最简单直接的理解方式就是按照你的做题逻辑顺序来写
所以做题的逻辑顺序至关重要,确保不重不漏地确保方案。
逻辑正确跑出来答案正确即可,不要过分地去深究内在实现,会很纠结。
注意dfs下一层要恢复现场,这是必需的。
深究不外乎:递归下一层+置false回溯上一层用+去掉无用的分支剪枝
//从大到小排个序,优先放重猫。
//一直往下搜索,答案是唯一的。
//放得下猫就继续往下加
//放不下就再另外开一辆,继续放
//分两个分支去放
//开一辆继续放其他猫的有一个分支
//开另一辆只放一只猫的也有一个分支
import java.util.*;
public class Main{
static int N=20;
static int n,m;
static int arr[]=new int [N];
static int ans=N;
static int car[]=new int [N];
static int cat[]=new int[N];
public static void main(String []args){
Scanner in = new Scanner(System.in);
n=in.nextInt();
m=in.nextInt();
for(int i=0;i<n;i++)cat[i]=in.nextInt();
Arrays.sort(arr,0,n);
//从小到大排个序
Reverse(arr,0,n-1);
//再从大到小排个序,优先放重猫
dfs(0,0);
System.out.println(ans);
}
//直接把他看成是第一遍模拟,剩下的递归处理即可。
public static void dfs(int u,int k){
if(k>=ans)return;
if(u==n){
//走到n时,即为找到答案ans=当前小车的数量k
ans=k;
return;
}
//考虑猫都放一辆车的情况
for(int i=0;i<k;i++){
if(cat[u]+car[i]<=m){
car[i]+=cat[u];
dfs(u+1,k);
car[i]-=cat[u];
//恢复现场,便于下一次加猫操作
}
}
//考虑猫只放一辆车的情况
car[k]=cat[u];
dfs(u+1,k+1);
//每次dfs会用到一辆车,所以需要加一。
car[k]=0;
//恢复现场
}
public static void Reverse(int q[],int l,int r)
//反转函数 -->从大到小排个序
{
for(int i=l,j=r;i<j;i++,j--){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}