贪心、优先队列-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
从右往左看,黄色表示选择做的作业,灰色表示已经做了,绿色是最后没做的
代码
#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
代码
#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;
}