贪心总结

偶尔的一点想法:
首先,应该认识到贪心这种思想是贯穿各个方面的题目的。贪心的原则:保持最优的原则,怎么好办怎么来。
其次,经常是题目让求什么你就贪心哪一个,获得这一要求的最优解。
重点是:有的贪心还需要用到各个方面的知识,排序、前缀和、矩阵等等。
在一些dp题目中,贪心这一思想也扮演着重要角色。

问题 F: 【贪心】零件分组

时间限制: 1 Sec 内存限制: 64 MB

题目描述
某工厂生产一批棍状零件,每个零件都有一定的长度(Li)和重量(Wi)。现在为了加工需要,要将它们分成若干组,使每一组的零件都能排成一个长度和重量都不下降(若 i<j,则 Li<=Lj,Wi<=Wj)的序列。请问至少要分成几组?
输入
第一行为一个整数 N(N<=1000),表示零件的个数。第二行有 N 对正整数,每对正整数表示这些零件的长度和重量,长度和重量均不超过 10000。
输出
仅一行,即最少分成的组数。
样例输入
5
8 4 3 8 2 3 9 7 3 5
样例输出
2
题目大意:有两个排序标准长度和重量,要求两者按照非严格递增顺序排序,形成的组数最少。

解题思路:
按照两个标准是比较麻烦的,首先可以以其中的一个标准升序排序,不妨以长度升序排序,这样在后面的操作中只考虑重量的大小就可以了。
既然是贪心,就是要求组数最少,每一次处理一个重量的时候,要把它尽量放在序号小的组里,那么就需要记录每个组的最大重量是多少,可以用数组记录,这样最终数组的大小其实就是最终的答案了。

#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include <cstdio>
//#define local
using namespace std;

typedef unsigned long long ull;
typedef long long ll;

const int N = 1000+5;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;

int n;
struct node
{
    int l,w;
    bool operator<(const node& b)const{
       if(l!=b.l) return l<b.l;
       else return w<b.w;
    }
}a[N];

int main()
{
#ifdef local
   freopen("input.txt","r",stdin);
#endif
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].l,&a[i].w);
    sort(a+1,a+n+1);
    int ans=0;
    int b[N];
    for(int i=1;i<=n;i++){
        int p=0;
        for(int j=1;j<=ans;j++){
            if(b[j]<=a[i].w){
                b[j]=a[i].w;
                p=1;
                break;
            }
        }
        if(!p) b[++ans]=a[i].w;
    }
    printf("%d",ans);
    return 0;
}

问题 O: 【贪心】智力大冲浪

时间限制: 1 Sec 内存限制: 128 MB

题目描述
小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者m元。先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则:

首先,比赛时间分为n个时段(n≤500),它又给出了很多小游戏,每个小游戏都必须在规定期限ti前完成(1≤ti≤n)。如果一个游戏没能在规定期限前完成,则要从奖励费m元中扣去一部分钱wi,wi为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,小伟很想赢得冠军,当然更想赢取最多的钱!注意:比赛绝对不会让参赛者赔钱!

输入
共4行。
第1行为m,表示一开始奖励给每位参赛者的钱;
第2行为n,表示有n个小游戏;
第3行有n个数,分别表示游戏1到n的规定完成期限;
第4行有n个数,分别表示游戏1到n不能在规定期限前完成的扣款数。

输出
仅1行,表示小伟能赢取最多的钱。
样例输入
10000
7
4 2 4 3 1 4 6
70 60 50 40 30 20 10
样例输出
9950

题目大意:
n个时间段内有n个游戏,一个游戏在一个时间段完成,每个游戏有一个罚款,要求罚款数最少。

解题思路:
要求罚款数最少→罚款数多的先进行→结构体按照罚款数降序
可能在一天的时间段多个游戏,所以需要标记这一天用没用。没用的话,直接用掉;用了的话,往前面寻找没用的时间段用掉,实在找不到,则就要扣掉罚款了。

#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include <cstdio>
//#define local
using namespace std;

typedef unsigned long long ull;
typedef long long ll;

const int N = 1000+5;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;

int m,n;
struct node
{
    int s,t;
    bool operator<(const node& b)const{
       if(s!=b.s)
           return s>b.s;
       else
           return t>b.t;
    }
}a[N];
int vis[N];
int main()
{
#ifdef local
   freopen("input.txt","r",stdin);
#endif
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i].t);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i].s);
    sort(a+1,a+n+1);
//    for(int i=1;i<=n;i++)
//        printf("%d %d\n",a[i].t,a[i].s);
    vis[0]=1;
    for(int i=1;i<=n;i++){
        int day=a[i].t;
        //if(vis[day]) m-=a[i].s;
        while(day>0&&vis[day]) day--;
        if(day<=0) m-=a[i].s;
        else vis[day]=1;
    }
    printf("%d",m);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值