暑假每日算法学习打卡(十一)----[USACO 2007 Jan S]Protecting the Flowers,华华听月月唱歌,「土」巨石滚滚(贪心)【牛客】

[USACO 2007 Jan S]Protecting the Flowers

题目描述 
Farmer John went to cut some wood and left N (2 ≤ N ≤ 100,000) cows eating the grass, as usual. When he returned, he found to his horror that the cluster of cows was in his garden eating his beautiful flowers. Wanting to minimize the subsequent damage, FJ decided to take immediate action and transport each cow back to its own barn.
Each cow i is at a location that is Ti minutes (1 ≤ Ti ≤ 2,000,000) away from its own barn. Furthermore, while waiting for transport, she destroys Di (1 ≤ Di ≤ 100) flowers per minute. No matter how hard he tries, FJ can only transport one cow at a time back to her barn. Moving cow i to its barn requires 2 × Ti minutes (Ti to get there and Ti to return). FJ starts at the flower patch, transports the cow to its barn, and then walks back to the flowers, taking no extra time to get to the next cow that needs transport.
Write a program to determine the order in which FJ should pick up the cows so that the total number of flowers destroyed is minimized.
输入描述:
Line 1: A single integer N
Lines 2..N+1: Each line contains two space-separated integers, Ti and Di, that describe a single cow's characteristics
输出描述:
Line 1: A single integer that is the minimum number of destroyed flowers
示例1
输入
6
3 1
2 5
2 3
3 2
4 1
1 6
输出
86

翻译:

 思路:这个类型的贪心题在排序是有一点小套路的,题目中排序要注意的无非就是距离T和吃花的速度D这两个两到底谁排在前面结果更优,下面看我的分析,注意数据范围,int只能过60%

 

 AC代码:

#include <bits/stdc++.h>

using namespace std;
struct f
{
    int l,r;
    double x;
}s[100009];
bool comp(f a,f b)
{
    return a.x<b.x;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&s[i].l,&s[i].r);
        s[i].x=s[i].l/(s[i].r*1.0);
    }
    sort(s+1,s+1+n,comp);
    long long ans=0,sum=0;
    for(int i=2;i<=n;i++)
    {
        //cout<<s[i].l<<" "<<s[i].r<<endl;
       sum+=s[i-1].l*2;
       ans+=sum*s[i].r;
       //cout<<sum<<" "<<ans<<endl;

    }
    cout << ans << endl;
    return 0;
}

华华听月月唱歌

题目描述 
月月唱歌超级好听的说!华华听说月月在某个网站发布了自己唱的歌曲,于是把完整的歌曲下载到了U盘里。然而华华不小心把U盘摔了一下,里面的文件摔碎了。月月的歌曲可以看成由1到N的正整数依次排列构成的序列,它现在变成了若干个区间,这些区间可能互相重叠。华华想把它修复为完整的歌曲,也就是找到若干个片段,使他们的并集包含1到N(注意,本题中我们只关注整数,见样例1)。但是华华很懒,所以他想选择最少的区间。请你算出华华最少选择多少个区间。因为华华的U盘受损严重,所以有可能做不到,如果做不到请输出-1。
输入描述:
第一行两个正整数N、M,表示歌曲的原长和片段的个数。
接下来M行,每行两个正整数L、R表示第i的片段对应的区间是[L,R]。
输出描述:
如果可以做到,输出最少需要的片段的数量,否则输出-1。
示例1
输入
4 2
1 2
3 4
输出
2
示例2
输入
4 2
1 1
3 4
输出
-1
示例3
输入
10 5
1 1
2 5
3 6
4 9
8 10
输出
4
备注:
1\le L\le R\le10^9, 1\le N\le 10^9,1\le M\le 10^51≤L≤R≤10^9 ,1≤N≤10^9,1≤M≤10^5

思路:跟上一题大差不差,对结构体排序时分情况,对左端点从小到大排序

#include <bits/stdc++.h>

using namespace std;
struct f
{
    int l,r;
} s[100006];
bool comp(f a,f b)
{
    return a.l<b.l;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d",&s[i].l,&s[i].r);
    }
    sort(s+1,s+1+m,comp);
    int ri,ans=0,c=0,k=1;
   while(c<n)
   {
       ri=0;
       while(s[k].l<=c+1&&k<=m)
       {
           ri=max(ri,s[k].r);
           k++;
       }
       if(ri>=c)
       {
           c=ri;
           ans++;
       }
       else
       {
           ans=-1;
           break;
       }
   }
    cout<<ans<<endl;
    return 0;
}

「土」巨石滚滚

题目描述 
帕秋莉掌握了一种土属性魔法

她使用这种魔法建造了一个大型的土球,并让其一路向下去冲撞障碍

土球有一个稳定性x,如果x < 0,它会立刻散架

每冲撞一个障碍,土球会丧失ai的稳定性,冲撞之后,又会从障碍身上回馈bi的稳定性

帕秋莉想知道,如果合理的安排障碍的顺序,在保证土球不散架的情况下,是否可以将障碍全部撞毁呢?

输入描述:
输入一个整数T,代表T组数据,每组数据中:
前一行两个整数n , m,表示障碍个数和土球的稳定性
接下来一行两个整数,分别表示障碍的ai和bi
输出描述:
若可以,输出“Yes”(不含引号),否则输出“No”(不含引号)
示例1
输入
1
5 50
49 49
52 0
5 10
26 24
70 70
输出
No
备注:
Σn <= 500000, 1<=m<=100000,0<=a,b<=100000

思路:排序的变量选择

if(x.v>0&&y.v>0)
    return x.a<y.a;

 else if(x.v<0&&y.v<0)
        return x.b>y.b;
 else return x.v>y.v;

#include <bits/stdc++.h>

using namespace std;
struct f
{
    int a,b,v;
} s[500001];
bool comp(f x,f y)
{
    if(x.v>0&&y.v>0)
    return x.a<y.a;
   else if(x.v<0&&y.v<0)
        return x.b>y.b;
    else
        return x.v>y.v;

}
int main()
{
    int n,m,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d",&s[i].a,&s[i].b);
            s[i].v=s[i].b-s[i].a;
        }
        sort(s+1,s+1+n,comp);
        int k=0;
        long long sum=m;
        for(int i=1; i<=n; i++)
        {
            sum-=s[i].a;
            if(sum<0)
            {
                k=-1;
                break;
            }
            sum+=s[i].b;
        }
        if(k==-1)
            cout << "No" << endl;
        else
            cout<< "Yes" <<endl;
    }
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值