CCF-CSP 29次 第二题【202303-2 垦田计划】

法一:
70分:优先队列
对基础耗时大的优先进行处理

#include 
#include 
#include 
#include 
#include 

using namespace std;

typedef pair PII;

const int N = 100010;

int n, m, k;
priority_queue, less> q;

int main()
{
	scanf("%d%d%d", &n, &m, &k);
	
	int t_min = 1e8;
	for (int i = 0; i < n; i ++ )
	{
		int t, c;
		scanf("%d%d", &t, &c);
		q.push({t, c});
		t_min = min(t_min, t);
	}
	
	int sum = 0;
	while (q.size())
	{
		auto a = q.top();
		q.pop();
		
		int t = a.first, c = a.second;
		
		if (t >= k && (sum + c) <= m)
		{
			sum += c;
			t -- ;	
			q.push({t, c});
		}
		else 
		{
			q.push({t, c});
			break;
		}
		
	}

	cout << q.top().first << endl;

	return 0;
}

/*
4 9 2
6 1
5 1
6 2
7 1
*/

法二:
100分:二分答案

#include 
#include 
#include 

using namespace std;

const int N = 100010;

int n, m, k;
int t[N], c[N];

bool check(int mid)
{
	int sum = 0;
	for (int i = 0; i < n; i ++ )
		if (t[i] > mid)
			sum += (t[i] - mid) * c[i];
	if (sum <= m) return true;
	else return false; 
}

int main()
{
	scanf("%d%d%d", &n, &m, &k);
	
	int maxt = 0;
	for (int i = 0; i < n; i ++ ) 
	{
		cin >> t[i] >> c[i]; 
		maxt = max(maxt, t[i]);
	}
	
	int l = k, r = maxt;
	while (l < r)
	{
		int mid = l + r >> 1;
		if (check(mid)) r = mid;
		else l = mid + 1;
	}
	
	cout << l << endl; 
	return 0;
}

/*
4 9 2
6 1
5 1
6 2
7 1
*/

法三:对法一的改进

  • 100分:对相同耗时的区域合并处理
  • 同样从耗时最多的区域开始
#include 
#include 
#include 

using namespace std;

const int N = 100010;

int n, m, k;
int t[N], c[N];
int cnt[N]; // 统计 不同耗时减少一天需要的资源总和 

int main()
{
	scanf("%d%d%d", &n, &m, &k);
	
	int maxt = 0;
	for (int i = 0; i < n; i ++ ) 
	{
		cin >> t[i] >> c[i]; 
		maxt = max(maxt, t[i]);
		cnt[t[i]] += c[i];
	}
	
	int i = 0;
	for (i = maxt; i >= k; i -- )
	{
		if (cnt[i] > m) break;
		m -= cnt[i];
		cnt[i - 1] += cnt[i];
	}
	
	cout << i << endl;
	
	return 0;
}

/*
4 9 2
6 1
5 1
6 2
7 1
*/

你可能感兴趣的:(c++,算法,图论,数据结构)