• 51nod贪心算法教程


       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
  • 相关阅读:
    java实现23种设计模式之中介者模式
    java实现23种设计模式之访问者模式
    java实现23种设计模式之状态模式
    java实现23种设计模式之备忘录模式
    java实现23种设计模式之命令模式
    java实现23种设计模式之责任链模式
    VS2012+OpenCV2.4.9+OpenTLD环境搭建
    Real-time Compressive Tracking
    OpenTLD相关资料
    华为面试题
  • 原文地址:https://www.cnblogs.com/wolf940509/p/4793445.html
Copyright © 2020-2023  润新知