题目大意:有一些作业规定了完成日期,如果没有在规定的日期完成就会就会扣掉期末的成绩,一天只能够完成一门作业,现在Ignatius想尽可能的减少所扣的成绩。
题目分析:说好的动态规划专题为什么有贪心; 其实很简单的一个贪心啦:(but刚看到题目没有想出来); 主要原因大脑中没有这种贪心模型。。。
试想一下,如果只能选择一些课,放弃一些课,你会怎么选择; 当然是完成扣份大的课,这样才能够让结果最优;但是有时间限制了应该怎么办呢,我们还是应该尽可能的优先完成扣份大的课,这样如果起冲突,也是放弃扣份小的课; 那么优先扣份大的课应该怎么选才能让结果最优呢? 如果截止时间是x,我们可以选择在第一天完成,也可以直到x天完成,应该在哪一天呢。看例子吧
A 3, 5; (表示课程a的作业,时间期限是第三天,如果没有完成扣5分), 同理 (B 1,1);这两门课,如果我们希望优先完成A,但是如果A放在了第一天,会导致B扣份,但是很明显我们如果先做在第2天做A,第一天写B是可以一份不扣的; 这样时间选择就出来了,应该最少的占据别的课的时间;(选择放在最后的期限,如果依然对别的课时间产生了影响,这样的影响就是不可避免的;
最优贪心出来了;
看代码,很简单的:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
// 这道题貌似是个贪心, 不开心:
int n, used[1000+10];
struct Node{
int v, t;
}node[1000+10];
bool cmp(const Node &a, const Node &b){
return a.v > b.v;
}
int main()
{
int T;
scanf("%d", &T);
while(T--){
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%d", &node[i].t);
for(int i = 0; i < n; ++i) scanf("%d", &node[i].v);
sort(node, node+n, cmp);
// 贪心选择;
int ans = 0;
memset(used, 0, sizeof(used));
for(int i = 0; i < n; ++i){
int x = node[i].t;
for( ; x >= 1; --x) if(used[x] == 0) { used[x] = 1; break; }
if(x < 1) ans += node[i].v;
}
printf("%d\n", ans);
}
return 0;
}