贪心-Doing Homework again HDU - 1789

题目

https://vjudge.net/problem/HDU-1789

思路一

思路一是,让价值尽量大的作业,尽量往后安排。

为了实现思路一,我们需要从后往前遍历”时间”,在每个时间节点选择满足当前条件的最大值,其中最大值我们使用优先队列实现。

以样例3为例,如图所示

1
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4    

贪心-Doing Homework again HDU - 1789

从右往左看,黄色表示选择做的作业,灰色表示已经做了,绿色是最后没做的

代码

#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;

struct node {
	int time, price;
	friend bool operator < (struct node a, struct node b)
	{
		if (a.price != b.price)	return a.price < b.price;
		else return a.time < b.time;
	}//使用小于号,对于优先队列,效果是price大的靠近top;对于sort函数,会把price小的排在数组前面
};

bool cmp(node a, node b) {
	return a.time > b.time;
}

int main(void) {
	int T = 0;
	cin >> T;
	while (T--) {
		priority_queue<node> Q;
		node arr[1005];
		int N, total = 0, ddl = 0;
		cin >> N;
		
		for (int i = 0; i < N; i++) {
			cin >> arr[i].time;
			ddl = ddl > arr[i].time ? ddl : arr[i].time;
		}
		for (int i = 0; i < N; i++) {
			cin >> arr[i].price;
			total += arr[i].price;
		}
		
		sort(arr, arr + N, cmp);
		int j = 0;
		for (int i = ddl; i >= 1; i--) {//错误:i >= 0
			for (; arr[j].time >= i && j < N; j++) {//错误:1. time >= ddl 2. 缺少&& j < N
			//	printf("%d has been push\n", arr[j].time);
				Q.push(arr[j]);
			}
			if (!Q.empty()) {
			//	printf("total is %d, Qtop is %d\n", total, Q.top().price);
				total -= Q.top().price;
				Q.pop();
			}
		}
		cout << total << endl;
	}
	
	return 0;
}

思路二

思路二的核心其实和思路一一样——让价值尽量大的作业,尽量往后安排。但是实现的方法不一样,既然我们想要让价值大的往后排,那我们不是只要让它在最后一天完成就好了?但这样可能会有重复,没关系,那就让它往前一天,还是不行就两天,以此类推。为此我们需要将价值从大到小排序。

还是以样例3为例子,价值从大到小,如图所示

1
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4    

贪心-Doing Homework again HDU - 1789

代码

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;

struct node {
	int time, price;
};

bool cmp(node a, node b) {
	return a.price > b.price;
}

int main(void) {
	int T = 0;
	cin >> T;
	while (T--) {
		priority_queue<node> Q;
		node arr[1005];
		int vis[1005];
		memset(vis, 0, sizeof(vis));
		int N, total = 0, spend = 0, ddl = 0;
		cin >> N;
		
		for (int i = 0; i < N; i++) {
			cin >> arr[i].time;
			ddl = ddl > arr[i].time ? ddl : arr[i].time;
		}
		for (int i = 0; i < N; i++) {
			cin >> arr[i].price;
			total += arr[i].price;
		}
		
		sort(arr, arr + N, cmp);
		for (int i = 0; i < N; i++) {
		//	for (int k = 1; k <= ddl; k++)	printf("%d ", vis[k]);	cout << endl;
			int j;
			for (j = arr[i].time; j >= 1 && vis[j] != 0; j--){}//这里很多i啊j啊,一定要沉下心来理清逻辑
			vis[j] = arr[i].price;
		}
		//for (int k = 1; k <= ddl; k++)	printf("%d ", vis[k]);	cout << endl;
		for (int i = 1; i <= ddl; i++) spend += vis[i];
		cout << total - spend << endl;
	}
	return 0;
}

参考博客

  1. https://www.cnblogs.com/blumia/p/hdu1789.html
  2. https://blog.csdn.net/liluoyu_1016/article/details/78938559
上一篇:第4章-8 求分数序列前N项和 (15 分)


下一篇:L1-054 福到了 (15 分)