hdu 1789 Doing Homework again 贪心
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1789
很久没做贪心,这道题看了好久没思路,后来看了别人的代码,顿时感觉自己弱爆了有木有。。。。
思路:
预处理:先根据扣分的多少按从大到小进行排序(扣分多的在前)。
然后根据贪心的策略:每次选择当前扣分最多的作业,然后从其截止日期那天开始,如果当前没有任务,则将那天标记为1(表示做当前的作业,初始化为0),然后就可以将当前作业的扣分赋值为0(表示已经有时间做,不用扣分),最后将每种作业遍历一边后,剩余的非0的分数相加即为答案。
证明:
对于截止日期为n的m种作业,如果m小于n 那么扣分最少肯定为0
如果m>n 假设一种作业排序为a1,a2,a3,a4......am 且 扣分情况为a1>a2>a3.....>am
那么做 此 顺序的前n种作业 ,肯定比选其他n种的扣分要少。
那么对于不同的截止日期,我们每次都对其按截止日期内的作业按扣分从大到小完成,最后的扣分一定是最少的。
解释的可能不太清楚,如果还是不懂的话,可以留言联系啊。。。。
代码如下:
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 class people 8 { 9 public: 10 int score; 11 int day; 12 }; 13 people p[1010]; 14 15 bool cmp(people a,people b) 16 { 17 return a.score>b.score; 18 19 } 20 bool ok[1010]; 21 int n; 22 int main() 23 { 24 int t; 25 cin>>t; 26 while(t--) 27 { 28 memset(ok,0,sizeof(ok)); 29 scanf("%d",&n); 30 for(int i=0;i<n;i++) 31 scanf("%d",&p[i].day); 32 for(int i=0;i<n;i++) 33 scanf("%d",&p[i].score); 34 sort(p,p+n,cmp); 35 for(int i=0;i<n;i++) 36 { 37 int t=p[i].day; 38 39 if(ok[t]==0) 40 { 41 ok[t]=1; 42 p[i].score=0; 43 } 44 else 45 { 46 while(ok[t]) 47 { 48 if(t==0) break; 49 t--; 50 } 51 if(t) {ok[t]=1; p[i].score=0;} 52 53 } 54 } 55 int ans=0; 56 for(int i=0;i<n;i++) 57 ans+=p[i].score; 58 cout<<ans<<endl; 59 } 60 return 0; 61 }
代码如下: