机试指南part6——贪心策略

贪心策略——总是做出当前最好的选择
1.问题分解成为多个子问题
2.子问题求局部最优解
3.局部最优解组合成原问题的解

简单贪心

#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;

const int MAXN=1000;

struct JavaBean
{
    double weight;
    double cost;
};

JavaBean arr[MAXN];

bool Compare(JavaBean x,JavaBean y)
{
    return x.weight/x.cost>y.weight/y.cost;
}

int main()
{
    int n,m;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        if(n==-1&&m==-1)
        {
            break;
        }
        for(int i=0;i<n;++i)
        {
            scanf("%lf%lf",&arr[i].weight,&arr[i].cost);
        }
        sort(arr,arr+n,Compare);
        double answer=0;
        for(int i=0;i<n;++i)
        {
            if(m>=arr[i].cost)
            {
                m-=arr[i].cost;
                answer+=arr[i].weight;
            }else
            {
                answer+=arr[i].weight*(m/arr[i].cost);
                m=0;
                break;
            }
        }
        printf("%.3f\n",answer);
    }
    return 0;
}

#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;

const int MAXN=100000+10;

long long gun[MAXN];
long long monster[MAXN];

bool Compare(long long x,long long y)
{
    return x>y;
}

int main()
{
    int caseNumber;
    scanf("%d",&caseNumber);
    while(caseNumber--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;++i)
        {
            scanf("%lld",&gun[i]);
        }
        for(int i=0;i<m;++i)
        {
            scanf("%lld",&monster[i]);
        }
        sort(gun,gun+n,Compare);
        sort(monster,monster+m);
        long long answer=0;
        for(int i=0;i<n;++i)
        {
            if(i>=m||gun[i]<=monster[i])
            {
                break;
            }
            answer+=gun[i]-monster[i];
        }
        printf("%lld\n",answer);
    }
    return 0;
}

#include<iostream>//箱子
#include<cstdio>
#include<algorithm>

using namespace std;

const int MAXN=1e5+10;

int length[MAXN];

bool Compare(long long x,long long y)
{
    return x>y;
}

int main()
{
        int n,l;
        scanf("%d%d",&n,&l);
        for(int i=0;i<n;++i)
        {
            scanf("%d",&length[i]);
        }
        sort(length,length+n);
        int left=0;
        int right=n-1;
        int answer=0;
        while(left<=right)
        {
            if(length[left]+length[right]<=l)
            {
                left++;
                right--;
            }
            else
            {
                right--;
            }
            answer++;
        }
        printf("%d\n",answer);
    return 0;
}

最大的最小间距:二分策略 最值问题→判定性问题

#include<iostream>//最大的最小值
#include<cstdio>
#include<algorithm>

using namespace std;

const int MAXN=1e5+10;

int arr[MAXN];

bool Judge(int n,int m,int distance)
{
    int current=arr[0];
    int number=1;
    for(int i=1;i<n;++i)
    {
        if(arr[i]-current>=distance)
        {
            number++;
            current=arr[i];
        }
        if(number>=m)
        {
            return true;
        }
    }
    return false;
}

int main()
{
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
           for(int i=0;i<n;++i)
           {
               scanf("%d",&arr[i]);
           }
           sort(arr,arr+n);
           int left=1;
           int right=arr[n-1]-arr[0];
           while(left<=right)
           {
               int middle=left+(right-left)/2;
               if(Judge(n,m,middle))
               {
                   left=middle+1;
               }
               else
               {
                   right=middle-1;
               }
           }
           printf("%d\n",right);
        }
    return 0;
}

#include<iostream>//最小值
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

const int MAXN=1e5+10;

int water[MAXN];

bool Judge(int n,int k,int time)
{
    int sum=0;
    for(int i=0;i<n;++i)
    {
        if(water[i]>time)
        {
            sum+=ceil((water[i]-time)*1.0/(k-1));
        }
        if(sum>time)
        {
            return false;
        }
    }
    return true;
}

int main()
{
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;++i)
        {
            scanf("%d",&water[i]);
        }
        int k;
        scanf("%d",&k);
           sort(water,water+n);
           if(k==1)
           {
               printf("%d\n",water[n-1]);
           }
           else
           {
              int left=1;
              int right=water[n-1];
              while(left<=right)
           {
               int middle=left+(right-left)/2;
               if(Judge(n,k,middle))
               {
                   right=middle-1;
               }
               else
               {
                   left=middle+1;
               }
           }
           printf("%d\n",left);
           }
    return 0;
}

区间贪心

#include<iostream>//看尽可能多的节目
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

const int MAXN=100+10;

struct program
{
    int startTime;
    int endTime;
};

program arr[MAXN];

bool Compare(program x,program y)
{
    return x.endTime<y.endTime;
}

int main()
{
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            if(n==0)
            {
                break;
            }
            for(int i=0;i<n;++i)
            {
                scanf("%d%d",&arr[i].startTime,&arr[i].endTime);
            }
            sort(arr,arr+n,Compare);
            int current=0;
            int answer=0;
            for(int i=0;i<n;++i)
            {
                if(current<=arr[i].startTime)
                {
                    current=arr[i].endTime;
                    answer++;
                }
            }
            printf("%d\n",answer);
        }

    return 0;
}

#include<iostream>//覆盖范围尽可能小
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

const int MAXN=1000+10;

struct Interval
{
    double left;
    double right;
};

Interval arr[MAXN];

bool Compare(Interval x,Interval y)
{
    return x.left<y.left;
}

int main()
{
        int n,d;
        int caseNumber=0;
        while(scanf("%d%d",&n,&d)!=EOF)
        {
            if(n==0&&d==0)
            {
                break;
            }
            bool flag=true;
            for(int i=0;i<n;++i)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                if(y>d)
                {
                    flag=false;
                }else
                {
                    arr[i].left=x-sqrt(d*d-1.0*y*y);
                    arr[i].right=x+sqrt(d*d-1.0*y*y);
                }
            }
            if(!flag)
            {
                printf("Case %d:%d\n",++caseNumber,-1);
            }else
            {
                sort(arr,arr+n,Compare);
                double current=arr[0].right;
                int answer=1;
                for(int i=1;i<n;++i)
                {
                    if(arr[i].left<=current)
                    {
                        current=min(current,arr[i].right);
                    }else
                    {
                        current=arr[i].right;
                        answer++;
                    }
                }
                printf("Case %d:%d\n",++caseNumber,answer);

            }

        }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值