首页 > 编程语言 >信息学奥赛初赛天天练-75-NOIP2016普及组-完善程序-二分答案、二分查找、贪心算法、贪心策略

信息学奥赛初赛天天练-75-NOIP2016普及组-完善程序-二分答案、二分查找、贪心算法、贪心策略

时间:2024-08-25 16:48:20浏览次数:6  
标签:二分 nn mid 初赛 while 处应 贪心

1 完善程序 (单选题 ,每小题3分,共30分)

郊游活动

有 n名同学参加学校组织的郊游活动,已知学校给这 n名同学的郊游总经费为 A元,与此同时第 i位同学自己携带了 Mi 元。为了方便郊游,活动地点提供 B(≥n) 辆自行车供人租用,租用第 j辆自行车的价格为 Cj元,每位同学可以使用自己携带的钱或者学校的郊游经费,为了方便账务管理,每位同学只能为自己租用自行车,且不会借钱给他人,他们想知道最多有多少位同学能够租用到自行车。(第四、五空 2.5 分,其余 3分)

本题采用二分法。对于区间 [l,r],我们取中间点 mid 并判断租用到自行车的人数能否达到 mid。判断的过程是利用贪心算法实现的。

源程序

#include <iostream>
using namespace std;
01 #define MAXN 1000000
02 
03 int n, B, A, M[MAXN], C[MAXN], l, r, ans, mid;
04 
05 bool check(int nn) {
06 	int count = 0, i, j;
07 	i = ①;
08 	j = 1;
09 	while (i <= n) {
10 		if(②)
11 			count += C[j] - M[i];
12 		i++;
13 		j++;
14 	}
15 	return ③;
16 }
17 	
18 void sort(int a[], int l, int r) {
19 	int i = l, j = r, x = a[(l + r) / 2], y;
20 	while (i <= j) {
21 		while (a[i] < x) i++;
22 		while (a[j] > x) j--;
23 		if (i <= j) {
24 			y = a[i]; a[i] = a[j]; a[j] = y;
25 			i++; j--;
26 		}
27 	}
28 if (i < r) sort(a, i, r);
29 if (l < j) sort(a, l, j);
30 }
31 
32 int main() {
33 	int i;
34 	cin >> n >> B >> A;
35 	for (i = 1; i <= n; i++)
36 		cin >> M[i];
37 	for (i = 1; i <= B; i++)
38 		cin >> C[i];
39 	sort(M, 1, n);
40 	sort(C, 1, B);
41 	l = 0;
42 	r = n;
43 	while (l <= r) {
44 		mid = (l + r) / 2;
45 		if(④){
46             ans = mid;
47 			l = mid + 1;
48 		}else
49 			r = ⑤;
50 	}
51 	cout << ans << endl;
52 	return 0;
53 }

1 ①处应填( )

2 ②处应填( )

3 ③处应填( )

4 ④处应填( )

5 ⑤处应填( )

2 相关知识点

二分答案

二分答案顾名思义,它用二分的方法枚举答案,并且枚举时判断这个答案是否可行

直接对答案进行枚举查找,接着判断答案是否合法。如果合法,就将答案二分进一步靠近,如果不合法,就接着二分缩小判断。这样就可以大大的减少时间。

二分中有时可以得可行得答案,但不是最大的,继续向右靠近,求出最大值

 int ans = 1;
 int l = 1,r = 100000;//在1~100000之间的整数枚举 
 while(l <= r){
     int m = l + (r - l) / 2;
     if(check(m)){//满足 则进行向右缩小范围 看看有没有更大的 
         ans = m;//可能多次赋值 最后一定是可能的最大值 
         l = m + 1;
      }else{//不满足缩小边长 向左缩小范围 用更小边长继续尝试 
         r = m - 1;
	  } 
  }

二分找边界

//左闭右闭 while left right 最终left=right+1
while(left<=right)  left = mid + 1; right =mid-1;
//左闭右开 while left right 最终left=right
while(left<right)   left = mid + 1; right =mid;
//左开右闭 while left right 最终left=right
while(left<right)   left=mid;       right=mid-1;
//左开右开 while left right 最终left=right-1
while(left+1<right) left=mid;       right=mid;

二分查找时间复杂度

二分查找每次都缩小或扩大为原来的一半,所以也是Olog(n)

贪心算法

所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择 。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的 局部最优解

例题

某商店不能电子支付,钱柜里的货币只有 25 分、10 分、5 分和 1 分四种硬币,如果你是售货员且要找给客户 41 分钱的硬币,如何安排才能找给客人的钱既正确且硬币的个数又最少?

分析

钱币保证最大面额大于其他小于它的面额之和,保证了每次选择最大的没有其他优于这个组合

即 选择了25 即使选择10+5+1=16都比25小

每次选择找零面额最大的,每次都是本次最优(局部最优),根据钱币面额本身的性质可知,可以保证全局最优

3 思路分析

求最多有多少位同学能够租用到自行车,总共n位同学,1~n 位同学之间二分的方法判定是否可以能租

判定是否可以租,使用贪心算法,具体如下

贪心策略,较多钱的同学去租相对便宜的车

//判定nn位同学是否可以租到自行车
05 bool check(int nn) {
06 	int count = 0, i, j;
07 	i = ①;//n-nn+1 取钱较多的nn个人 贪心算法
08 	j = 1;//租车费用从小到大租,贪心算法
09 	while (i <= n) {
10 		if(②)//M[i]<C[j] 如果当前同学带的钱不够,累加起来,看看学校经费是否够
11 			count += C[j] - M[i];
12 		i++;
13 		j++;
14 	}
15 	return ③;//count<=A 看学校经费是否够 ,经费够可以租nn辆车,经费不够不能租nn辆车
16 }

1 ①处应填( n-nn+1 )

分析

07 	i = ①;//n-nn+1 取钱较多的nn个人 贪心算法
例如
n=10 nn=6 
从10-6+1=5,到10这6个人
因为前面按从小到大进行了排序
5~10这6人,比1~6这6人有钱

2 ②处应填( M[i]<C[j] )

分析

10 		if(②)//M[i]<C[j] 如果当前同学带的钱不够,累加起来,看看学校经费是否够
如果钱带的够,就可以租n辆车
为了让钱不够的同学租到车,需要从学校经费借钱,把借的钱累加起来,后续判定是否超出经费

3 ③处应填( count<=A )

分析

15 	return ③;//count<=A 看学校经费是否够 ,经费够可以租nn辆车,经费不够不能租nn辆车

4 ④处应填( check(mid) )

分析

/*二分思想,计算左右边界的中间租车数量,如果可以组,看看能否可以租更多,如果不能租,看看少租一些车是否可行
mid = (l + r) / 2;
check(mid)
*/
43 	while (l <= r) {
44 		mid = (l + r) / 2;
45 		if(④){
46             ans = mid;
47 			l = mid + 1;
48 		}else
49 			r = ⑤;
50 	}

5 ⑤处应填( mid-1 )

分析

二分边界,如下为左右闭区间,l=mid+1,r=mid-1
所以填mid-1
43 	while (l <= r) {

标签:二分,nn,mid,初赛,while,处应,贪心
From: https://www.cnblogs.com/myeln/p/18379113

相关文章

  • CSP-J 2023 初赛试题解析(第三部分:完善程序(1-2))
    第一题补全后完整代码:#include<iostream>#include<vector>usingnamespacestd;intfind_missing(vector<int>&nums){intleft=0,right=nums.size()-1;while(left<right){intmid=left+(right-left)/2;if(nums[mi......
  • 浅谈二分图
    定义二分图,又称二部图,英文名叫Bipartitegraph。二分图是什么?节点由两个集合组成,且两个集合内部没有边的图。换言之,存在一种方案,将节点划分成满足以上性质的两个集合。性质如果两个集合中的点分别染成黑色和白色,可以发现二分图中的每一条边都一定是连接一个黑色点和一个白......
  • 洛谷SCP 2024 第一轮(初赛 J 组)模拟题解析(第三部分:完善程序(1-2))
    完善程序一(补全)#include<bits/stdc++.h>usingnamespacestd;constintMAXN=100000;intn;intvis[MAXN],a[MAXN];vector<int>ans;intcheck(intk){intx=n,top=0;for(inti=0;i<=k;i++)vis[i]=0;while(x......
  • 历年CSP-J初赛真题解析 | 2015年CSP-J初赛阅读程序(23-26)
    学习C++从娃娃抓起!记录下CSP-J备考学习过程中的题目,记录每一个瞬间。附上汇总贴:历年CSP-J初赛真题解析|汇总_热爱编程的通信人的博客-CSDN博客#include<iostream>usingnamespacestd;intmain(){inta,b,c;a=1;b=2;c=3;if(a>b){......
  • 数列(贪心思维题)(很有意思哦)(读者 rp +++++++)
    数列(贪心思维题)(很有意思哦)(读者rp+++++++)序这是前段时间做的一道题,蛮有思维含量的,而且对于代码实现能力也有一定要求。作者也交了好多发......
  • 整体二分
    前置知识:二分,一些数据结构如树状数组用途:用于解决多次可二分可离线的询问。可以使用整体二分解决的题目应具有以下性质:询问的答案具有可二分性。修改对判定答案的贡献互相独立,修改之间互不影响效果。修改如果对判定答案有贡献,则贡献为一确定的与判定标准无关......
  • c++贪心、模拟超详细讲解
    一、贪心算法基础1.1定义与原理定义:贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。原理:贪心算法通过局部最优选择来构造全局最优解。在每一步,算法都做出一个看起来最优的决策,期望通过局部最优达到全局......
  • 信息学奥赛初赛天天练-74-NOIP2016普及组-基础题5-树、父节点、根节点、叶子节点、非
    NOIP2016普及组基础题521从一个4×4的棋盘(不可旋转)中选取不在同一行也不在同一列上的两个方格,共有()种方法。22约定二叉树的根节点高度为1。一棵结点数为2016的二叉树最少有()个叶子结点;一棵结点数为2016的二叉树最小的高度值是()2相......
  • 力扣热题100_贪心算法_55_跳跃游戏
    文章目录题目链接解题思路解题代码题目链接55.跳跃游戏给你一个非负整数数组nums,你最初位于数组的第一个下标。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标,如果可以,返回true;否则,返回false。示例1:输入:nums=[......
  • wqs 二分学习笔记
    蒟蒻的第一篇学习笔记qwqwqs二分用于解决此类问题n个物品,从中选恰好m个,最大化收益。而且你发现,如果没有选m个的限制,这道题是非常好做的。使用前提1、恰好选k个,至多至少不行2、答案满足凸性什么是凸性?设选i个物品时的收益为fi如果把它画成函数,那么它长这样(上凸包)或者这样......