本题为简单的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 */