CodeVS 4228 小猫爬山 - DFS

传送门

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

 

posted @ 2018-04-06 21:11  dprswdr  阅读(244)  评论(0编辑  收藏  举报