HDU 1789 Doing Homework again 【队列+贪心】

来源:互联网 发布:java考试报名 编辑:程序博客网 时间:2024/05/16 15:56

Doing Homework again

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8873    Accepted Submission(s): 5230


Problem Description
Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test. And now we assume that doing everyone homework always takes one day. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.
 

Input
The input contains several test cases. The first line of the input is a single integer T that is the number of test cases. T test cases follow.
Each test case start with a positive integer N(1<=N<=1000) which indicate the number of homework.. Then 2 lines follow. The first line contains N integers that indicate the deadlines of the subjects, and the next line contains N integers that indicate the reduced scores.
 

Output
For each test case, you should output the smallest total reduced score, one line per test case.
 

Sample Input
333 3 310 5 131 3 16 2 371 4 6 4 2 4 33 2 1 7 6 5 4
 

Sample Output
035
 

Author
lcy
 

Source
2007省赛集训队练习赛(10)_以此感谢DOOMIII
 
思路:
 
       题目让求扣分最少,所以我们要将扣分比较多的排到前面,把扣分比较少的排到后面,然后从扣分多的开始做,那个扣分多的在扣分多的那天做,如果第二个扣分多的同样也在那天交,那就提前一天做,用过的天要进行标记,如果在后面有的那天交的作业并且那一天被占用了,要用它前面的天做,如果没有,都被占了,那就只能放弃不做了,这个不做的作业也是它之前分数最少的!就按照这样的思路遍历一遍作业,最终求出要扣的总分!
 
 
代码
 
#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;struct node {int score;int num;}a[1005];int cmp(node u,node v){return u.score>v.score;}int main(){int b[1005];int T,n,i,j,k,t,d,e,sum;scanf("%d",&T);while(T--){memset(b,0,sizeof(b));scanf("%d",&n);for(i=0;i<n;i++){scanf("%d",&a[i].num);}for(i=0;i<n;i++)scanf("%d",&a[i].score);sort(a,a+n,cmp);for(i=0,sum=0;i<n;i++){for(j=a[i].num;j>0;j--)//看看它所要求的最后期限那一天是否被占用,没被占用就用这一天写作业,并进行标记,{if(!b[j])// 如果被占用,则区遍历之前的天是否被占用,如果没有,则进行标记,否则加到sum上! {{b[j]=1;break;}}if(j==0)  sum+=a[i].score;}printf("%d\n",sum); }return 0;}

之前按照对时间按照从小到大的顺序排序试了试,太多情况需要考虑,最终还是考虑错了,所以现在贴个错误代码,以示警告:
 
 
/*错误代码,请勿参考!!!!!!!!! */#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;struct node {int score;int num;}a[1005];int cmp(node u,node v){if(u.num==v.num)//按照时间从小到大排序,如果时间相同 return u.score>v.score;return u.num<v.num;}int main(){int b[1005];int T,n,i,j,k,t,d,e;scanf("%d",&T);while(T--){//memset(b,0,sizeof(b));scanf("%d",&n);    for(i=0;i<n;i++)scanf("%d",&a[i].num);for(i=0;i<n;i++)scanf("%d",&a[i].score);sort(a,a+n,cmp);for(i=1,j=0,k=2,t=a[0].num,d=a[0].score;i<n;i++){if(a[i].num==t&&k>t){for(e=0;e<i;e++){if(a[e].score<a[i].score)a[i].score=a[e].score;}j+=a[i].score;  k++;}else if(a[i].num==t&&k<=t){k++;} else{k=t+2;t=a[i].num;}}printf("%d\n",j);}return 0;}
 
 
再来一个用队列的方法做代码:
 
/*为了熟悉一下队列,再将这道题用队列的方法做一遍!!!!!!!!主要是在队列的成员数比天数大的时候能它够将把大的来替换小的,从而将小的退出,加到sum上! */#include <stdio.h>#include <queue>#include <algorithm>using namespace std;struct node{int day;int score;}a[1005];int cmp(node u,node v){if(u.day==v.day)return u.score<v.score;return u.day<v.day;}int main(){int T,n,i,j,k,sum;scanf("%d",&T);while(T--){priority_queue<int,vector<int>,greater<int> >q;scanf("%d",&n);for(i=0;i<n;i++){scanf("%d",&a[i].day);}for(i=0;i<n;i++){scanf("%d",&a[i].score);}sort(a,a+n,cmp);for(i=0,sum=0;i<n;i++){if(a[i].day>q.size()){q.push(a[i].score);}else {if(a[i].score>q.top()){sum+=q.top();q.pop();q.push(a[i].score);}else{sum+=a[i].score;}}}printf("%d\n",sum);}return 0;}


0 0