关于搜索时的优化

这里拿C++一本通(白书第三版)上DFS的课后题12最佳调度问题举例子。(没看过题去自己翻书)

这是光盘里附带的标程:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 int n,k,a[101],f[1001],ans;
 6 void find(int x,int y)
 7 {
 8     int i;
 9     if (y>=ans) return;
10     if (x>n)
11     {
12      if (y<ans) ans=y;
13      return;
14     }
15     for(i=1;i<=k;i++)
16     {
17      f[i]=f[i]+a[x];
18      find(x+1,max(y,f[i]));
19      f[i]=f[i]-a[x];
20     }
21 }
22 int main()
23 {
24     int i;
25     scanf("%d%d",&n,&k);
26     for(i=1;i<=n;i++)
27       scanf("%d",&a[i]);
28     memset(f,0,sizeof(f));
29     ans=2147483647;
30     find(1,0);
31     printf("%d",ans);
32 }

然后我们拿一组附带的测试数据:

in

19 4
21 60 24 44 81 71 42 9 51 56 41 79 23 60 85 86 72 10 15

 

out 

233

就发现标程T了= =

我们改一改标程,加上点玄学优化:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 int n,k,a[101],f[1001],ans;
 6 void find(int x,int y)
 7 {
 8     int i;
 9     if (y>=ans) return;
10     if (x>n)
11     {
12      if (y<ans) ans=y;
13      return;
14     }
15     for(i=1;i<=k;i++)
16     {
17      f[i]=f[i]+a[x];
18      find(x+1,max(y,f[i]));
19      f[i]=f[i]-a[x];
20     }
21 }
22 int main()
23 {
24     int i;
25     scanf("%d%d",&n,&k);
26     for(i=1;i<=n;i++)
27       scanf("%d",&a[i]);
28     sort(a+1,a+1+n);
29     reverse(a+1,a+1+n);
30     memset(f,0,sizeof(f));
31     ans=2147483647;
32     find(1,0);
33     printf("%d",ans);
34 }

相比标程,改动后的程序只在28,29两行加了个sort排序并且反了过来。(reverse是把数组里的元素改成逆序,就是把sort排完序的从小到大改成从大到小,你写个自定义比较函数也OK)

然后= =神奇的事情就发生了,跑的比标程快多了2333。

对于搜索的优化,除了对初始数据进行排序(从大到小和从小到大的结果是不一样的,比如这个题如果你是按从小到大排再搜索依旧是TLE),还可以在搜索前进行一次贪心,先认为你的贪心结果是对的,这样的话就算贪到的结果不是正解,也比较接近正解,这样在搜索的时候比你贪到的答案大的就可以直接跳过了。(当然你要考虑你贪心的时间复杂度,不要贪来贪去贪的慢。)

posted @ 2018-03-07 10:38  Misaka_Azusa  阅读(212)  评论(0编辑  收藏  举报
Live2D