基本算法之贪心算法

看了刘汝佳大牛的黑书果然很有体会,虽然很难,但是真的题题经典,一定要坚持坐下去,下面我们来说说贪心法

     贪心算法即是每次选择局部最优策略进行实施,而不去考虑对今后的影响。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

下面来看一个题目:

POJ1042 钓鱼(黑书)

链接:http://poj.org/problem?id=1042

 贪心:为了不讨论在路上花费的时间,可以枚举到过的湖:比如:a=j 表示到过湖1、2、..、j相应的, 花在路上的时间
* 就是 t[1]+t[2]+..+t[j-1] (显然每段路只会走一次) 于是算出time,表示花在钓鱼上的时间,往回走并没有好处,因此我们不选择往回走
*     这样一来,就不同再考虑路上的时间了,可以认为John有瞬间移动,哪个湖鱼多,就到哪个湖钓(当然 湖的编号 满足 1 <= ~ <=a)

我们依次枚举究竟要在前多少个湖钓鱼,那么我们可以先将路上的时间计算好,然后人为我们可以在这几个湖之间瞬间转移,每次挑一个上钩率最高的湖去钓即可。

代码参看的是金海峰大牛,同时学会了新的代码风格,以后将会沿用下去

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<algorithm>
 8 #include<vector>
 9 #include<map>
10 #include<stack>
11 using namespace std;
12 const int maxn=30;
13 int f[maxn],d[maxn],t[maxn],ans[maxn];
14 int n,h,ansf;
15 bool p=false;
16 
17 void init()  //输入部分,用函数更好
18 {
19     cin>>h;
20     h*=12;
21     ansf=-1;
22     for(int i=1;i<=n;i++)
23         cin>>f[i];
24     for(int i=1;i<=n;i++)
25         cin>>d[i];
26     for(int i=1;i<n;i++)
27         cin>>t[i];
28 }
29 
30 void make(int a,int time)
31 {
32     int ls[maxn],ans1[maxn],mx,mxi,fish=0;
33     memset(ans1,0,sizeof(ans1));
34     for(int i=1;i<=a;i++)
35         ls[i]=f[i];
36     while(time>0)  //此处开始用贪心法,求出最优方案
37     {
38         mx=-1;
39         mxi=-1;
40         for(int i=1;i<=a;i++)
41             if(mx<ls[i])
42         {
43             mx=ls[i];
44             mxi=i;
45         }
46         fish+=mx;
47         ans1[mxi]+=1;
48         ls[mxi]=0>ls[mxi]-d[mxi]?0:ls[mxi]-d[mxi];
49         time--;
50     }
51     if(fish<ansf)
52         return;
53     if(fish>ansf)
54     {
55         for(int i=1;i<=n;i++)
56             ans[i]=ans1[i];
57         ansf=fish;
58         return;
59     }
60     int j=1;
61     while(j<=n&&ans[j]==ans1[j])
62         j++;
63     if(ans1[j]>ans[j])
64         for(int i=1;i<=n;i++)
65         ans[i]=ans1[i];
66 }
67 void work()
68 {
69     int time=0;
70     t[0]=0;
71     for(int i=1;i<=n;i++)  //“瞬间转移”经典做法
72     {
73         time+=t[i-1];
74         make(i,h-time);
75     }
76 }
77 
78 void print()  //输出部分,用函数更好
79 {
80     if(p)
81         cout<<endl;
82         for(int i=1;i<n;i++)
83             cout<<ans[i]*5<<", ";
84         cout<<ans[n]*5<<endl<<"Number of fish expected: "<<ansf<<endl;
85         p=true;
86 }
87 int main()
88 {
89     while(cin>>n)
90     {
91         if(n==0)
92             break;
93         init();
94         work();
95         print();
96     }
97     return 0;
98 }
View Code

 

posted @ 2015-05-03 15:17  wolf940509  阅读(419)  评论(0编辑  收藏  举报