本题为简单的DFS,但需要一些小剪枝。
我们遍历的状态有3个:当前需安放的第i只小猫now、已经花费的钱数cnt、各矿车剩余的空间rst[]。
我们把rst[]作为回溯的状态,把now和cnt作为转移的参数。
先遍历不新建矿车的情况:枚举每个矿车,若能安放,则继续遍历该情况。
再遍历新建矿车的情况。
还要加上一些剪枝:
1.最优性剪枝:若当前cnt已经>=ans,就return。
2.优化搜索顺序:重量大的小猫所能安放的情况比重量小的要少,因此我们可以先对小猫的重量进行降序排序,以缩小搜索树的范围。
AC Code:
1 #include<cstdio>
2 #include<algorithm>
3 #include<cstring>
4 using namespace std;
5 int n,w;
6 int c[50];
7 int ans=(1<<30);
8 int rst[50];
9 void dfs(int now,int cnt)
10 //now=当前为第i只小猫 cnt=花钱数
11 {
12 if(cnt>=ans) return;
13 if(now==n+1)
14 {
15 ans=min(ans,cnt);
16 return;
17 }
18 for(int i=1;i<=cnt;i++)
19 {
20 if(rst[i]+c[now]<=w)
21 {
22 rst[i]+=c[now];
23 dfs(now+1,cnt);
24 rst[i]-=c[now];
25 }
26 }
27 rst[cnt+1]=c[now];
28 dfs(now+1,cnt+1);
29 rst[cnt+1]=0;
30 }
31 bool cmp(int a,int b)
32 {
33 return a>b;
34 }
35 int main()
36 {
37 scanf("%d%d",&n,&w);
38 for(int i=1;i<=n;i++)
39 scanf("%d",&c[i]);
40 sort(c+1,c+n+1,cmp);
41 dfs(1,0);
42 printf("%d",ans);
43 return 0;
44 }
45 /*
46 5 1996
47 1
48 2
49 1994
50 12
51 29
52 */