码迷,mamicode.com
首页 > 编程语言 > 详细

51nod贪心算法教程

时间:2015-09-09 01:07:48      阅读:302      评论:0      收藏:0      [点我收藏+]

标签:

   51nod确实是一个好oj,题目质量不错,wa了还放数据,学习算法来说挺好的,这次我做了几个水的贪心,虽然水,但是确实都很典型。

教程链接:http://www.51nod.com/tutorial/list.html

  完美字符串

   约翰认为字符串的完美度等于它里面所有字母的完美度之和。每个字母的完美度可以由你来分配,不同字母的完美度不同,分别对应一个1-26之间的整数。
   约翰不在乎字母大小写。(也就是说字母F和f)的完美度相同。给定一个字符串,输出它的最大可能的完美度。例如:dad,你可以将26分配给d,25分配给a,这样整个字符串完美度为77。
   分析: 由排序不等式,出现次数最多的字母显然应该给26。所以这个题目变成了统计每种字母出现的次数了,然后按照出现次数从大到小,依次分配从高到低的权值。这就是最朴素的贪心思想。

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<string>
 6 #include<algorithm>
 7 #include<cctype>
 8 #include<cstdlib>
 9 using namespace std;
10 const int maxn=27;
11 int a[maxn];
12 string s;
13 bool cmp(const int a,const int b)
14 {
15     return a>b;
16 }
17 int main()
18 {
19     while(cin>>s)
20     {
21         memset(a,0,sizeof(a));
22         for(int i=0;i<s.length();i++)
23             a[tolower(s[i])-a]++;
24         sort(a,a+26,cmp);
25         long long sum=0;
26         int b=26;
27         for(int i=0;i<26;i++)
28         {
29             sum+=a[i]*b;
30             --b;
31         }
32         cout<<sum<<endl;
33     }
34     return 0;
35 }
View Code

 

活动安排问题

  有若干个活动,第i个开始时间和结束时间是[Si,fi),只有一个教室,活动之间不能交叠,求最多安排多少个活动?

   分析:看似最不对的策略——结束时间越早的活动优先,才是正确的贪心。

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 const int maxn=10000+1;
 9 typedef struct
10 {
11     int start;
12     int over;
13 }point;
14  point p[maxn];
15 const int cmp(const  point a, const  point b)
16 {
17     return a.over<=b.over;
18 }
19 int main()
20 {
21     int n;
22     while(cin>>n)
23     {
24         memset(p,0,sizeof(p));
25         for(int i=0;i<n;i++)
26             cin>>p[i].start>>p[i].over;
27         sort(p,p+n,cmp);
28         int cnt=1;
29         for(int i=0;i<n;i++)
30         {
31             for(int j=i+1;j<n;j++)
32             {
33                 if(p[i].over<=p[j].start)
34                 {
35                     i=j;
36                     cnt++;
37                     continue;
38                 }
39             }
40         }
41         cout<<cnt<<endl;
42     }
43     return 0;
44 }
View Code

 

活动安排问题二

 有若干个活动,第i个开始时间和结束时间是[Si,fi),活动之间不能交叠,要把活动都安排完,至少需要几个教室?

 上一题的升级版

  分析:如果只需要教室的个数,我们可以把所有开始时间和结束时间排序,遇到开始时间就把厚度加1,遇到结束时间就把厚度减1,显然最初始和最后结束时的厚度是0,在一系列厚度变化的过程中,峰值(最大值)就是最多同时进行的活动数,也是我们至少需要的教室数。

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<vector>
 7 #include<algorithm>
 8 using namespace std;
 9 const int maxn=10000+1;
10 int te[maxn],ts[maxn];
11 int main()
12 {
13     int n;
14     while(cin>>n)
15     {
16         for(int i=0;i<n;i++)
17             scanf("%d%d",&ts[i],&te[i]);
18             sort(ts,ts+n);
19             sort(te,te+n);
20             int cnt=0;
21             int mx=0,j=0;
22             for(int i=0;i<n;i++)
23             {
24                 if(ts[i]<te[j])
25                 {
26                     cnt++;
27                     if(cnt>mx)
28                         mx=cnt;
29                 }
30                 else if(ts[i]>te[j])
31                 {
32                     //cnt--;
33                     j++;
34                 }
35                 else
36                 {
37                     j++;
38                 }
39             }
40             cout<<mx<<endl;
41     }
42     return 0;
43 }
View Code

 

独木舟问题

n个人,已知每个人体重,独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人。显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟?

分析:按照人的体重排序,最轻的人跟最重的人尽量安排在一条船上,如果超过就安排最重的

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<string>
 7 #include<cctype>
 8 #include<algorithm>
 9 #include<vector>
10 using namespace std;
11 const int maxn=10001;
12 int a[maxn];
13 bool cmp(long long a,long long b)
14 {
15     return a>b;
16 }
17 int main()
18 {
19     int n;
20     long long m;
21     while(cin>>n)
22     {
23         scanf("%lld",&m);
24         long long x;
25         for(int i=0;i<n;i++)
26         scanf("%lld",&a[i]);
27         sort(a,a+n,cmp);
28         long long cnt=0;
29         int i=0;
30         while(i<n)
31         {
32             if(a[n-1]+a[i]<=m)
33             {
34                 cnt++;
35                 n--;
36                 i++;
37             }
38             else
39             {
40                 i++;
41                 cnt++;
42             }
43             //cout<<a[i]<<"jk"<<a[n-1-i]<<endl;
44         }
45         //cout<<i<<"io"<<endl;
46         cout<<cnt<<endl;
47     }
48     return 0;
49 }
View Code

 

任务执行顺序

有N个任务需要执行,第i个任务计算时占R[i]个空间,而后会释放一部分,最后储存计算结果需要占据O[i]个空间(O[i] < R[i])。

分析:

     可以抽象成,从一个整数开始,每次减去a,再加上b (a,b都是正数),要求每次操作都不产生负数。
      令a[i] = R[i], b[i] = R[i] – O[i],O[i] < R[i],有0<b[i]<a[i]。 所以尽管每次有减有加,但是加的没有减的多,总数在不断减小。所以——按照b[i]不增的顺序排序,是最“有利”的。

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cctype>
 5 #include<vector>
 6 #include<string>
 7 #include<cmath>
 8 #include<algorithm>
 9 using namespace std;
10 const int maxn=100001;
11 long long r[maxn],o[maxn],b[maxn],a[maxn];
12 bool cmp(long long a,long long b)
13 {
14     return a>b;
15 }
16 int main()
17 {
18     int n;
19     while(cin>>n)
20     {
21         for(int i=0;i<n;i++)
22             scanf("%lld%lld",&r[i],&o[i]);
23             for(int i=0;i<n;i++)
24             {
25                 a[i]=r[i];
26                 b[i]=r[i]-o[i];
27             }
28             sort(b,b+n,cmp);
29             long long mx=0x3fff;
30             long long ans=0;
31             for(int i=0;i<n;i++)
32             {
33                 ans-=a[i];
34                 if(ans<mx)
35                   mx=ans;
36                   ans+=b[i];
37             }
38             cout<<(0-mx)<<endl;
39     }
40     return 0;
41 }
View Code

 

51nod贪心算法教程

标签:

原文地址:http://www.cnblogs.com/wolf940509/p/4793445.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!