Doing Homework again
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3190 Accepted Submission(s): 1855
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.
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
3
3
3 3 3
10 5 1
3
1 3 1
6 2 3
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4
Sample Output
0
3
5
题目解释:完成作业,每项作业有所对应的得分以及完成的期限,超过期限未完成则扣分,问最少扣分是多少。
说起来这道题目我最初写的时候纠结了好久,然后,听了指点之后就有种豁然开朗的感觉。
Method:
看到此题,首先想到贪心,然后就是排序了。如何排呢?我是按照扣分从大到小来排(因为要得到最少扣分),如果扣分相同则按照完成期限从前到后来排(先完成时间紧的才是王道!)。
排完后开始一项一项来查,如果发现可以完成,就让这项作业在可以完成的最后期限那天完成,如果最后期限那天已经有扣分更高的作业占据了,就把时间往前推,如果有某天无事可做,就用那天来完成作业。为了完成上述步骤,你需要一个数组来记录每一天是否被占据。剩下的就是把代码敲出来了。有了思路代码应该很简单吧。
1 #include <stdio.h> 2 #include <string.h> 3 int T, N; 4 int main() 5 { 6 int t[1050], s[1050], i, j, date[1050], score, temp; //t[]是用来记录时间的,s[]是用来记录扣分的,date[]是用来记录某天是否用过的。 7 scanf("%d", &T); 8 while(T--) 9 { 10 score = 0; 11 memset(date, 0, sizeof(date)); 12 scanf("%d", &N); 13 for(i = 1; i <= N; i ++) 14 { 15 scanf("%d", &t[i]); 16 } 17 for(i = 1; i <= N; i ++) 18 { 19 scanf("%d", &s[i]); 20 } 21 for(i = 1; i <= N; i++) 22 { 23 for(j = i; j <= N; j ++) 24 { 25 if(s[i] < s[j]) 26 { 27 temp = s[i]; 28 s[i] = s[j]; 29 s[j] = temp; 30 temp = t[i]; 31 t[i] = t[j]; 32 t[j] = temp; 33 } 34 if(s[i] == s[j]) 35 { 36 if(t[i] > t[j]) 37 { 38 temp = t[i]; 39 t[i] = t[j]; 40 t[j] = temp; 41 temp = s[i]; 42 s[i] = s[j]; 43 s[j] = temp; 44 } 45 } 46 } 47 } 48 for(i = 1; i <= N; i ++) 49 { 50 if(date[t[i]] == 0) 51 date[t[i]] = 1; 52 else 53 { 54 for(j = t[i]-1; j >= 0; j --) 55 { 56 if(j == 0) 57 { 58 score += s[i]; 59 break; 60 } 61 if(date[j] == 0) 62 { 63 date[j] = 1; 64 break; 65 } 66 if(j == 1) 67 { 68 score += s[i]; 69 break; 70 } 71 } 72 } 73 } 74 printf("%d\n", score); 75 } 76 return 0; 77 }
做完这个题之后又看了看网上其他大神的代码,发现自己排序的方法很笨很繁琐,另外自己的代码也可以大幅度简化,下面贴一个其他人的代码
1 #include <stdio.h> 2 #include <stdlib.h> 3 struct Homework 4 { 5 int score; 6 int deadline; 7 }work[1000]; 8 int main() 9 { 10 int i, j; 11 int T, n; 12 int win, max, mark, sum; 13 scanf ("%d", &T); 14 while (T --) 15 { 16 scanf ("%d", &n); 17 max = 0; 18 for (i = 0; i < n; i ++) 19 { 20 scanf ("%d", &work[i].deadline); 21 if (work[i].deadline > max) 22 { 23 max = work[i].deadline; 24 } 25 } 26 sum = 0; 27 for (i = 0; i < n; i ++) 28 { 29 scanf ("%d", &work[i].score); 30 sum += work[i].score; 31 } 32 win = 0; 33 for (i = max; i > 0; i --) 34 { 35 max = 0; 36 mark = -1; 37 for (j = 0; j < n; j ++) 38 { 39 if (work[j].deadline >= i && work[j].score > max) 40 { 41 max = work[j].score; 42 mark = j; 43 } 44 } 45 if (mark != -1) 46 { 47 win += max; 48 work[mark].score = 0; 49 } 50 } 51 printf ("%d\n", sum - win); 52 } 53 return 0; 54 }
明显要简单,发现定义一个结构体来表示要省事好多啊!思路上也有区别,具体的大家自己体会吧。我的想法是最大众化的一种。
另外,在这篇文章里还想说一下排序的一些问题,最近看到了sort和qsort,很好用,我会在另一篇文章中仔细说一下。
ps.第一次写随笔,好多地方可能会很幼稚,不过我会努力坚持的,加油!
我们都是颜色不一样的海。
浙公网安备 33010602011771号