c语言贪心算法小游戏,贪心算法基础题(一)

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

**解析:**同活动安排问题,将线段按结束的点从小到大排列,只要下一个线段开始的点大于或等于前一个点结束的点即可。这样得出的线段数最多。 为什么不按开始时间排序,见下图。

c68407a78481ff5de056dffd2c7a8964.png

#include #includeusing 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;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值