#关于贪心(入门)

本文通过两个实例探讨了贪心算法的应用技巧,一是移除最少数量的障碍物使魔术师能够穿墙而过的问题,二是最大化同时吃草的奶牛数量问题。
刷是把贪心的题目都刷得差不多了,但其实自己对贪心的理解还不是很透彻,只是按照Oj的提示告诉自己 这题要用贪心的思想来解决。

个人认为这几道题目还是比较有emm比较有感觉。

题目描述

穿墙术是现代魔术表演中常见的一个节目。魔术中的穿墙人可以穿过预先设计好的若干道墙。所有的墙被安置在一个网格区域中,如图所示,‘?’表示墙所占据的网格,所有的墙都水平放置,宽度为1个单位,但长度可能不同。任何两道墙不会相互重叠,即任何一个‘?’不能同时属于两道或两道以上的墙。穿墙人的能量有限,每次表演至多只能穿过k道墙。 表演开始时,主持人让观众任选网格的某一列,然后穿墙人开始沿着此列从网格的上端穿过中间的每一道墙到达网格的底部。但如果观众所选择的那一列中有大于k道墙,则穿墙人的表演会失败。 例图所示,如果k=3,则穿墙人可以自上而下地穿过除第6列外的任何列,因为只有第6列需要穿越4道墙,但穿墙人在同一列上最多只能穿过3道墙。
pic

当所有的墙给出之后,如果知道穿墙人当前的能量K,我们希望移去最少数目的墙,才能使得穿墙人能够穿越任何一列。 对于图中的例子,如果k=3,穿墙人无法穿越第6列,但是只要把第3行的墙移去(不唯一),则穿墙人就可以穿过任意一列。因此对于这个例子最少需要移去1道墙。

输入格式

第一行是用空格隔开的两个整数n和k,其中1 ≤ n ≤ 100,0 ≤ k ≤ 100;n表示墙的数目,k表示穿墙人在同一列上最多能穿过多少道墙。接下来有n行,每行是用空格隔开的四个整数x1, y1, x2, y2,其中(x1, y1)和(x2, y2)分别表示一道墙的两个端点(注意,根据题意,一定有y1=y2)。x, y坐标的范围为[0, 100],左上角的坐标定为(0, 0)。

输出格式

只包含一个整数,即为了让穿墙人能够穿越任意一列所需要移去的最少的墙的数目。

样例数据

input

7 3 
0 0 3 0 
6 1 8 1
2 3 6 3 
4 4 6 4 
0 5 1 5 
5 6 7 6 
1 7 3 7

output

1
拿到题目其实是比较懵的。(日常三分钟读不懂题目)但其实仔细一想,并不难处理。

下面是代码

#include<bits/stdc++.h>
using namespace std;
int n,k;
struct wall{
    int t,w;
}walls[110];
int s[110]={};//'s' records the number of walls that the column already has
int result=0;

bool mycmp(wall a,wall b)
{
    return(a.w<b.w||(a.w==b.w&&a.t>=b.t));
}

void init()
{
cin>>n>>k;
int a,b,c,d;
for(int i=1;i<=n;i++)
{
cin>>a>>b>>c>>d;//b==d
    walls[i].t=min(a,c);
    walls[i].w=max(a,c);
}
}

void work()
{
    sort(walls+1,walls+n+1,mycmp);
int l=walls[1].t;
int r=walls[1].w;
    for(int i=l;i<=r;i++) s[i]++;
    for(int i=2;i<=n;i++)
    {
        for(int j=walls[i].t;j<=walls[i].w;j++)
            if(s[j]<=k-1) s[j]++;
else
            {
                result++;
break;
            }//end ,dismantling the wall
    }
}
int main()
{
    init();
    work();
    cout<<result;
    return 0;}
想来这道题目其实不难。

另一道游荡的奶牛,思路其实很明确也很简单,记录下牛的起始位置和终止位置排个序然后贪心去做(不会的时候就排序???),然而做这道题犯了一个很大毛病。

题目描述

FJ 有 N (1 <= N <= 50,000)头牛,FJ的草地可以认为是一条直线。 每只牛只喜欢在某个特定的范围内吃草。第i头牛喜欢在区间(S_i, E_i)吃草, (1 <= S_i < E_i; S_i < E_i<= 100,000,000).

奶牛们都很自私,他们不喜欢和其他奶牛共享自己喜欢吃草的领域,因此FJ要保证任意两头牛都不会共享他们喜欢吃草的领域。如果奶牛i和奶牛j想要同时吃草,那么要满足: S_i >= E_j 或者 E_i <= S_j. FJ想知道在同一时刻,最多可以有多少头奶牛同时吃草?

下面的样例有5头奶牛:
pic

这5头奶牛的范围分别是:(2, 4), (1, 12), (4, 5), (7, 10) (7, 8)。 显然,第1、3、4,共3只奶牛可以同时吃草,第1、3、5也可以。

输入格式

  • 第 1 行:一个整数: N
  • 第2..N+1行: 第i+1 行有两个整数: S_i 、 E_i

输出格式

*一行: 一个整数,最多可以有多少头牛同时吃草.

样例数据

input

5
2 4
1 12
4 5
7 10
7 8

output

3
下面是我的代码,8分的

#include<bits/stdc++.h>
using namespace std;
int n;
struct cow{
int begin,end;
}sec[50200];

void init()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>sec[i].begin>>sec[i].end;
}

bool mycmp(cow a,cow b)
{
return a.end<b.end;
}

int main()
{
init();
int sum=0,final;
    sort(sec+1,sec+1+n,mycmp);
final=sec[1].end;
for(int i=1;i<=n;i++)
{
if(sec[i+1].begin>=final)
{
final==sec[i+1].begin;
sum++;
}
}
cout<<sum;
return 0;
}

然后是AC代码。
#include<bits/stdc++.h>
using namespace std;
int n;
struct cow{
int begin,end;
}sec[50200];

void init()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>sec[i].begin>>sec[i].end;
}

bool mycmp(cow a,cow b)
{
return a.end<b.end;
}

int main()
{
init();
int sum=1,final;
    sort(sec+1,sec+1+n,mycmp);
final=sec[1].end;
for(int i=1;i<=n;i++)
{
if(sec[i+1].begin>=final)
{
final=sec[i+1].end;
sum++;
}
}
cout<<sum;
return 0;
}
真的,看上去是不是没什么差别,然而还是有差别的。唯一的不同就是最后一个循环里套的if语句中 final=sec[i+1].end//8分的是begin//   做这道题就是心态太好,思路明确,(我都是先把主程序敲好在另一个地方,然后搬进来的)于是,于是千查万查都查不出这个小错误。心态爆炸。

接下来也是一个需要铭记于心的警示。
巧克力根本不给看大佬代码还不能看自己错在哪个数据上我真是心态崩了。(第一次提交90我心情其实是不错的,看到没有数据我当场懵逼)

然后就是各种尝试,(有些修改无脑得很)
然后最后,最后,我成功地发现,问题其实是结构体数组开的大小
数据要求如图,

忘了需要开的数组是n+m的。。。。。
emmm这里是关于贪心,其实贪心并不是很难理解,主要是一种巧妙的解题思想,贪心标准的选择以及细节才是重点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值