求解獎學金問題--貪心


/*問題描述:有n門課(編號為0~n-1),每門課都有考試。為了拿到獎學金,必須滿足所有課程平均成績至少為avg。每門課由平時成績和考試成績相加得到,滿足為r。現知道每門課平均成績ai(0<=i<=n-1),若想讓這門課多考一分,需要花bi的時間復習。同時,也可能出現復習再多也不會超過滿分的分數。為了拿到獎學金,請問至少需要花多少時間??
輸入描述:每個測試用例第一行為整數n(1<=n<=200),表示課程數,接下來n行,每行兩個整數,分別表示一門課的平均成績ai和bi,最后一行輸入滿分r和希望到達的平均成績avg,以輸入n==0結束
4
80 5
70 2
90 3
60 1
100 92.5
0
樣例輸出:
100
分析:既然選擇用貪心,那么就要制定貪心准則。既然給定了avg平均成績和n,那么我們不難得出拿到獎學金的總分為n*avg,同時每門課的平均成績也已給出,那么二者之差就是我們需要復習之后提高的分數了。而且這個分數,要用最少的時間來獲得。
所以要對bi進行排序。
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<vector>
 6 #include<stack>
 7 #include<map>
 8 #include<set>
 9 #include<list>
10 #include<queue>
11 #include<string>
12 #include<algorithm>
13 #include<iomanip>
14 using namespace std;
15 #define MAX 201
16 int n;
17 struct score
18 {
19     /* data */
20     int ai;
21     int bi;
22     bool operator < (const score & s)const
23     {
24         return  bi < s.bi;//復習時間遞增排序
25     }
26 };
27 
28 score A[MAX];
29 int r;
30 double avg;
31 int effort = 0;
32 
33 void Solve()
34 {
35     int Sums = (int) n * avg;//需要達到的總分
36     int cursum = 0;
37     for(int i = 0 ; i< n; i ++)//現有課程的總分
38     {
39         cursum += A[i].ai;
40     }
41     sort(A,A + n);
42     for(int j = 0; j< n;j++)//貪心選擇
43     {
44         if(cursum >= Sums)//分數達到,結束選擇
45         {
46             break;
47         }
48     
49         int cur = cursum;
50         cursum += min(Sums - cursum ,r - A[j].ai);
51         effort += A[j].bi * min(Sums-cur,r - A[j].ai);
52     }
53 }
54 int main()
55 {
56     while(cin>>n && n != 0 )
57     {
58         for(int i = 0;i < n; i++)
59         {
60             cin>>A[i].ai>>A[i].bi;
61         }
62         cin>>r>>avg;
63         Solve();
64         cout<<effort<<endl;
65     }
66     return 0;
67 }
    for(int j = 0; j< n;j++)//貪心選擇
43     {
44         if(cursum >= Sums)//分數達到,結束選擇
45  { 46 break; 47  } 48 49 int cur = cursum; 50 cursum += min(Sums - cursum ,r - A[j].ai); 51 effort += A[j].bi * min(Sums-cur,r - A[j].ai); 52  }
針對這一段,簡單說一下,每門課已經按照單位復習時間遞增排了序,50行是為了找出 (需要達到的總分與目前總分的差,每門課的滿分r與當前平均成績ai的差)較小的那個,因為從單位復習時間最少的開始復習(同樣是總分加一分,當然是時間越少越好)。Sums-curcum==70,100-60=40,,所以花費時間為effort+= 1 * 40。即把60的成績復習到滿分,花費40分鍾,此時目前總分為340,還需30分,繼續循環單位復習時間第二小的那個,是70 ,2。Sums-cumin==30,100-70 ==30 ,所以這個復習到滿分剛好達到條件。此時(effort += 2 *(30)) == 100.所以最終至少需要花費100單位時間去復習。如果Sums-cursum  < r-A[j].ai  ,那就意味着當前課程不需要到滿分就能拿獎學金了,最后加上需要的時間就行了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM