zoukankan      html  css  js  c++  java
  • 贪心算法小结。今年暑假不AC&&Radar Installation&&Y2K Accounting Bug&&Minimal Coverage

                                                                               今年暑假不AC:http://acm.hdu.edu.cn/showproblem.php?pid=2037

    一个简单的贪心例题:

    思路:就是自己看:

     1 #include <iostream> 
     2 
     3 using namespace std; 
     4 
     5 int main() 
     6 
     7 {                             
     8 
     9     int a[100],b[100]; 
    10 
    11     int n; 
    12 
    13     int e=0; 
    14 
    15     int cont=0; 
    16 
    17     while(cin>>n&&n!=0){ 
    18 
    19         cont=0; 
    20 
    21         for(int i=0;i<n;i++) 
    22 
    23             cin>>a[i]>>b[i]; 
    24 
    25         for(int i=0;i<n;i++) 
    26 
    27             for(int j=i;j<n;j++)
    28 
    29                    { 
    30 
    31                 if(b[i]>b[j])
    32 
    33                    { 
    34 
    35                     swap(b[i],b[j]);  //交换位置
    36 
    37                     swap(a[i],a[j]);  //虽然只是冒泡法,这个问题还不会超时!
    38 
    39                 }                
    40 
    41             } 
    42 
    43         //取第一个        
    44 
    45         cont++;
    46 
    47         e=b[0]; 
    48 
    49         for(int i=1;i<n;i++){ 
    50 
    51             if(a[i]>=e) { 
    52 
    53                 cont++; 
    54 
    55                 e=b[i]; 
    56 
    57             }  
    58 
    59         } 
    60 
    61         cout<<cont<<endl; 
    62 
    63     } 
    64 
    65     return 0; 
    66 
    67 }  

    Radar Installationhttp://poj.org/problem?id=1328

    也是贪心算法。

    思路:先把每个点对应圆的取值范围表示出来,此题就转化成为线段相交的问题。之后就是左端排序,再求他们之间分成几块。

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    int main()
    {
        int n,m,i,a[1005],b[1005],j,s,q=0,k=0,sd;
        double c[1005],d[1005],e[1005],h;//要用double型!
    
      while(scanf("%d %d",&n,&m)!=EOF)
      {
          q++;k=0;
          if(n==0&&m==0)
            break;
          for(i=0;i<n;i++)
            {scanf("%d %d",&a[i],&b[i]);
            if(b[i]>m)
                k=1;
            }
            if(k==1)
                printf("Case %d: -1
    ",q);//
            else
            {
          for(i=0;i<n;i++)
            for(j=i;j<n;j++)
          {
              if(a[i]>a[j])
              {
                swap(a[i],a[j]);
                swap(b[i],b[j]);
              }
          }
           for(i=0;i<n;i++)
          {
              c[i]=sqrt(m*m-b[i]*b[i]);
          }
          for(i=0;i<n;i++)
          {
              d[i]=a[i]-c[i];
              e[i]=a[i]+c[i];
          }
          s=1;
          h=e[0];
          for(i=1;i<n;i++)
              if(d[i]>h)
              {
                  h=e[i];
                  s++;
              }
              else if(e[i]<h)
                     h=e[i];
          printf("Case %d: %d
    ",q,s);}
    
      }
       return 0;
    }

     Y2K Accounting Bug  http://poj.org/problem?id=2586

    题目难理解,但做起来不难。以下题意解释来自:優YoU http://user.qzone.qq.com/289065406/blog/1299234147

    实际上;只要讨论5种情况即可;(任一月固定盈余s,或固定亏损d).

    SSSSDSSSSDSS   4s<d       保证“连续5个月必亏损”,每连续5个月种至少1个月D,

                              保证可能有全年最大盈余,每连续5个月中至多4个月S

    SSSDDSSSDDSS   3s<2d      保证“连续5个月必亏损”,每连续5个月种至少2个月D,

    保证可能有全年最大盈余,每连续5个月中至多3个月S

    SSDDDSSDDDSS   2s<3d      保证“连续5个月必亏损”,每连续5个月种至少3个月D,

    保证可能有全年最大盈余,每连续5个月中至多2个月S

    SDDDDSDDDDSD   s<4d       保证“连续5个月必亏损”,每连续5个月种至少4个月D,

    保证可能有全年最大盈余,每连续5个月中至多1个月S

    DDDDDDDDDDDD   s>=4d      保证“连续5个月必亏损”,每连续5个月种至少5个月D,

    每月亏损,此情况全年必亏损

    要注意的是,前4种情况都仅仅是“可能有全年的盈余”,而不是“一定有全年的盈余”。

    但是若果一旦有盈余,必定是最大盈余

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    int main()
    {
        int n,m,t;
        while(scanf("%d %d",&n,&m)!=EOF)
        {
            if(n==0&&m==0)
                break;
            if(m>n*4)
            {
                t=n*10-m*2;
                if(t>0)
                    printf("%d
    ",t);
                else
                    printf("Deficit
    ");
            }
            else if(m*2>n*3)
            {
                t=n*8-m*4;
                if(t>0)
                    printf("%d
    ",t);
                else
                    printf("Deficit
    ");
            }
            else if(m*3>n*2)
            {
                t=n*6-m*6;
                if(t>0)
                     printf("%d
    ",t);
                else
                    printf("Deficit
    ");
            }
            else if(m*4>n)
            {
                t=n*3-m*9;
                if(t>0)
                    printf("%d
    ",t);
                else
                    printf("Deficit
    ");
            }
            else
                 printf("Deficit
    ");
        }
        return 0;
    }

    Minimal Coveragehttp://poj.org/problem?id=2620

    照样的贪心的方法,但注意这里排序一定不能用冒泡法!!!!!直接超时!

    题意就是:数轴上有n个闭区间[ai,bi],选择尽量少的区间覆盖一条指定的线段[s,t]。

    本人第一次用sort()来排序,这里要用结构体。贪心的算法一般就是先排序,再从小到大找关系就行了。

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    struct line
    {
        int left;
        int right;
    }a1[100000];
    bool comp(line i,line j)
    {
        if(i.left<j.left)
            return true;//这里是从小到大的排序。只要看left就行了right跟着一起排的。正符合题意。要想从大到小就是把小于符号变成大于!
        return false;从这里似乎看出对于结构体的这种排序,如果只说明一种,其他就默认地跟着那样排了!
    }
    int main()
    {
        int n,a,b,d=0,i,j,x=0,w=0,h,y=0,max1=0,max2,c[100000];
       scanf("%d",&n);
            while(scanf("%d %d",&a,&b)!=EOF)
            {
                if(a==0&&b==0)
                    break;
                    if(a<n&&b>0)
                {a1[d].left=a;a1[d].right=b;d++;}
            }
            sort(a1,a1+d,comp);
           for(;;)
            {
                y=0;
                max2=max1;
                max1=0;
                for(i=0;i<d;i++)
            {
                if(a1[i].left<=max2&&a1[i].right>max2)
                {
                    if(a1[i].right>max1)
                    {
                        max1=a1[i].right;c[x]=i;
                    }
                    y=1;
                }
        }
            x++;
            if(y!=1)
            {w=1;break;}
            if(max1>=n)
            {w=2;break;
            }
        }
        if(w==1)
            printf("No solution
    ");
        if(w==2)
        {
            printf("%d
    ",x);
            for(i=0;i<x;i++)
            {
                printf("%d %d
    ",a1[c[i]].left,a1[c[i]].right);
            }
        }
        return 0;
    }

     关于sort()一些常见用法:

    sort(a,a+n);默认的从小到大排序;

    等价于:

    bool comp(int a,int b)
    {
    return a<b;
    }
    sort(a,a+10,comp);

    而要从大到小排序:

    bool comp(int a,int b)
    {
    return a>b;
    }
    sort(a,a+10,comp);

  • 相关阅读:
    python学习(3)
    Python学习(2)
    powerDesigner的初步使用
    单阶经典检测器: YOLO V1 (一)
    单阶多层检测器: SSD(三)改进算法
    单阶多层检测器: SSD(二)算法综述
    单阶多层检测器: SSD(一)
    两阶经典检测器:Faster RCNN(三)改进算法
    【转载】http协议介绍
    【转载】dts介绍
  • 原文地址:https://www.cnblogs.com/tt123/p/3208424.html
Copyright © 2011-2022 走看看