贪心算法基础题(一)

A. 智力大冲浪

题目描述
小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者 m 元。先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则:首先,比赛时间分为 n 个时段,它又给出了很多小游戏,每个小游戏都必须在规定期限 ti前完成。如果一个游戏没能在规定期限前完成,则要从奖励费 m 元中扣去一部分钱 wi,wi为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,小伟很想赢得冠军,当然更想赢取最多的钱!注意:比赛绝对不会让参赛者赔钱!

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

输出格式
输出仅一行,表示小伟能赢取最多的钱。

样例
样例输入
10000
7
4 2 4 3 1 4 6
70 60 50 40 30 20 10
样例输出
9950
**解析:**若想罚款最少,就要再完成罚款较多的任务的同时多完成任务,所以先将任务按罚款多少降序排列,然后让任务最后期限完成,保证前面能完成更多的任务,倘若最后期限已有任务,则从最后期限向前遍历,遍历到没有任务的时候停止即可,若都有任务,则该任务不可能完成,算到罚款中。
代码

#include 
int main()
{
    int n,a,b,c,flag;
    long long int m,d=0;
    int l[500][5],l1[500];
    scanf("%lld%d",&m,&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&l[i][0]);
    }
    for(int j=1;j<=n;j++){
        scanf("%d",&l[j][1]);
        l1[j]=0;
    }
    for(int q=1;q=1;jj--){
            if(l1[jj]==0){
                l1[jj]=1;
                flag=0;
                break;
            }
        }
        if(flag==1){
            d+=l[ii][1];
        }
    }
    printf("%d",m-d);
    return 0;
}

B. 数列极差

题目描述
佳佳的老师在黑板上写了一个由 n 个正整数组成的数列,要求佳佳进行如下操作:每次擦去其中的两个数 a 和 b,然后在数列中加入一个数a×b+1,如此下去直至黑板上剩下一个数为止,在所有按这种操作方式最后得到的数中,最大的为 max,最小的为 min, 则该数列的极差定义为 M=max -min。
输入格式
第一行为一个正整数 n 表示正整数序列的长度;
在接下来的 n 行中,每行输入一个正整数。
接下来的一行有一个 0,表示数据结束。

输出格式
输出只有一行,为相应的极差 d。

样例
样例输入
3
1
2
3
0
样例输出
2
**解析:**每次删两个,通过计算我们可以知道每次删两个最大的得到的是最小值
每次删两个最小的,然后排序再删出最小的,最后得到的是最大的
代码

#include 
#include 
using namespace std;
int main()
{
    int n;
    int l[50005];
    long int a,b;
    scanf("%d",&n);
    if(n<=2){
        printf("%d",0);
    }
    else{
    for(int i=0;i<=n;i++){
        scanf("%d",&l[i]);
    }
    sort(l,l+n);
    b=l[n-1]*l[n-2]+1;
    for(int k=n-3;k>=0;k--){
        b=b*l[k]+1;
    }
    for(int j=0;j

C. 数列分段

题目描述
对于给定的一个长度为 N 的正整数数列 Ai ,现要将其分成连续的若干段,并且每段和不超过 M(可以等于 M),问最少能将其分成多少段使得满足要求。

输入格式
第一行包含两个正整数 N,M,表示了数列 Ai 的长度与每段和的最大值;
第二行包含 N 个空格隔开的非负整数 Ai。

输出格式
输出文件仅包含一个正整数,输出最少划分的段数。

样例
样例输入
5 6
4 2 4 5 1
样例输出
3
解析从头开始遍历,用一个值记录和,当加上下一个值大于M时,到此为一段,若加上下一个值等于M,则在下一个值为一段,这样段数最少,最后还要判断断尾与M的关系,如果等于M,直接输出,如果小于M,结果加一。
代码

#include 
int main()
{
    long long int n,m,a=0;
    int l[100005];
    int ans=0;
    scanf("%lld%lld",&n,&m);
    for(int i=0;im){
            a=l[i];
            ans++;
        }
    }
    if(a==0){
    printf("%d",ans);
    }
    else if(a

D. 线段

题目描述
数轴上有 n 条线段,选取其中 k 条线段使得这 k 条线段两两没有重合部分,问 k 最大为多少。

输入格式
第一行为一个正整数 n;
在接下来的 n 行中,每行有2个数 ai,bi,描述每条线段。

输出格式
输出一个整数,为 k 的最大值。

样例
样例输入
3
0 2
2 4
1 3
样例输出
2
**解析:**同活动安排问题,将线段按结束的点从小到大排列,只要下一个线段开始的点大于或等于前一个点结束的点即可。这样得出的线段数最多。 为什么不按开始时间排序,见下图。
贪心算法基础题(一)_第1张图片

#include 
#include
using namespace std;
struct line
{
    int a,b;
}l[1000005];
bool f(line n,line m)
{
    return n.b=c){
            c=l[x].b;
            ans++;
        }
    }
    printf("%d",ans);
    return 0;
}

你可能感兴趣的:(贪心算法基础题(一))