CCF刷题计划——垦田计划(手握map砍竹子)

垦田计划

计算机软件能力认证考试系统

刷题最有用的一集!做这道题的时候,我深刻感受到之前刷的题是有效果的QWQ。如果是以前,优先队列我是想都不会想的,如果是中间,优先队列只得70我就放弃了,但是现在,我刷过蓝桥杯 砍竹子,也就对这道题的优化有了眉目。

本题可以学到的:自定义类型优先队列的使用、map实现横向"砍竹子"

使用优先队列还超时了,这是我没想到的,但是好歹得了70分,而且复习了优先队列,还是不亏的。经过我的优化,还是把这道题做出来了。

70分:

cpp 复制代码
#include <iostream>
#include <queue>
using namespace std;
#define ll long long 
const int N=1e5+2; 
//思路:贪心吧,先将最高的那个打下来,放回去,然后再找最高,再打,直到资源用完或者最高的那个无法再减。
//看的这类问题就想起了 优先队列 

struct Infor	//田地信息 
{
	int time,cost;	//时间,减少一天的花费
	
	//使用自定义类型的优先队列需要重载运算符,多写几次就记住了
	Infor(int t,int c)
	{
		time=t;	cost=c;	
	} 
	bool operator < (const Infor& a) const	//大顶堆 
	{
		return time<a.time;
	}
};

priority_queue<Infor>pq;	// <当前开垦天数,减少一天的花费> 
int n,m,k;	//区域总数、资源总量、每块最少开垦天数 


int main()
{
	cin>>n>>m>>k;
	int time,cost;
	for(int i=0;i<n;i++)
	{
		cin>>time>>cost;
		pq.push({time,cost});
	} 
	
	while(m)	//当资源没用完 
	{
		time=pq.top().time;
		cost=pq.top().cost;
		
		if(time==k || m-cost<0)	//如果当前最大天数已经无法再减少
			break; 
		
		//到这都是能减少的
		m-= cost;
		time--;
		
		pq.pop();	//删除旧的 
		pq.push({time,cost});			//添加新的 
	}
	cout<<pq.top().time;
	return 0;
}

**优化的思绪(怎么想到这样优化的):**仔细想想还有哪里可以优化呢?其实break的条件可以再优化一下,想想,如果有100个田,有99块都能被材料减少,但是就是有一个无法满足,导致这些田都白减了,会浪费很多时间。如果可以有一个更高效的判断,或者不一个一个来减,直接减一截,那是不是好很多。

对!一次性减一截!这里我想起来之前刷蓝桥杯那个砍竹子,我们不一定要将一个田减一截,而可以将相同天数的田全部都减1!前者是纵向砍一大段,后者是横向砍一片,但是这一片都只向下减少了1。

经过我漫长的优化......(我一开始用map还没做出来,因为将totalcost的计算和向下迭代复杂化了,下面的代码就很满意)

AC:

cpp 复制代码
#include<iostream>
#include <map>
#include <vector>
using namespace std;
#define ll long long 
const int N=1e5+2;
const int inf=0x3f3f3f3f;

int n,m,k;
map<int,vector<int>>mp;	// <天数,相同天数的id集合> 
vector<int>c(N);
int ans=inf;

int main()
{
	cin>>n>>m>>k;
	int time,cost; 
	for(int i=0;i<n;i++)
	{
		cin>>time>>c[i];
		mp[time].push_back(i);
	}
	
	ll totalCost=0;
	
	//mp也是有顺序的,我们可以反向遍历将最大的key(也就是这里的time)进行处理
	auto it=mp.end();	//先指向最大的时间
	it--; 
	time=it->first;
	vector<int>cur=it->second;
	
	while(m>0)
	{
		for(auto id:cur)	//先将cur指向的田地加入到Totalcost   
			totalCost+=c[id];	//因为每次其实都是在上次的基础上进行负重增加,所以没必要从头到尾计算 
		
		if(m<totalCost || time==k)
		{
			cout<<time;
			return 0;
		}
		m-=totalCost;
		
		//逐渐向低天靠拢 
		time--;
		cur=mp[time];
	}
	return 0;
}
相关推荐
吴_知遇36 分钟前
【华为OD机试真题】428、连续字母长度 | 机试真题+思路参考+代码解析(E卷)(C++)
开发语言·c++·华为od
LaoWaiHang1 小时前
MFC案例:使用键盘按键放大、缩小窗口图像的实验
c++·mfc
山北雨夜漫步1 小时前
机器学习 Day14 XGboost(极端梯度提升树)算法
人工智能·算法·机器学习
到底怎么取名字不会重复1 小时前
Day10——LeetCode15&560
c++·算法·leetcode·哈希算法·散列表
chuxinweihui2 小时前
数据结构——二叉树,堆
c语言·开发语言·数据结构·学习·算法·链表
freexyn2 小时前
Matlab自学笔记五十一:(推荐)输入参数的数量和可变数量的输入
笔记·算法·matlab
陈大大陈2 小时前
基于 C++ 的用户认证系统开发:从注册登录到Redis 缓存优化
java·linux·开发语言·数据结构·c++·算法·缓存
纪元A梦2 小时前
华为OD机试真题——通过软盘拷贝文件(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
java·javascript·c++·python·华为od·go·华为od机试题
数据分析螺丝钉2 小时前
LeetCode 252 会议室 III(Meeting Rooms III)题解与模拟面试
算法·leetcode·职场和发展
小李独爱秋2 小时前
动态哈希映射深度指南:从基础到高阶实现与优化
数据结构·算法·哈希算法