首页 > 代码库 > NOIP2017 d1t1 期末考试

NOIP2017 d1t1 期末考试

题目描述:
有n位同学,每位同学都参加了全部的m门课程的期末考试,都在焦急的等待成绩的公布。第i位同学希望在第ti天或之前得知所.有.课程的成绩。如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程公布成绩,每等待一天就会产生C不愉快度。对于第i门课程,按照原本的计划,会在第bi天公布成绩。有如下两种操作可以调整公布成绩的时间:
1.将负责课程X的部分老师调整到课程Y,调整之后公布课程X成绩的时间推迟一天,公布课程Y成绩的时间提前一天;每次操作产生A不愉快度。
2.增加一部分老师负责学科Z,这将导致学科Z的出成绩时间提前一天;每次操作产生B不愉快度。
上面两种操作中的参数X,Y,Z均可任意指定,每种操作均可以执行多次,每次执行时都可以重新指定参数。现在希望你通过合理的操作,使得最后总的不愉快度之和最小
 
题解:

一开始的思路是这样的:由于这道题比较复杂,有多个变量,所以不太可能直接出答案,那么差不多就应该是枚举所有的出成绩天数了

推论一:出成绩的时间只取决于最后一课出成绩的时间,所以想要在第n天出成绩的话,就要让最后一课出成绩的时间小于等于第x天

推论二:让最后一课提前一天有两种方式,A<B那么就应该优先考虑方式一,A>B那么就应该优先考虑方式二,(但是注意方式一的使用次数是有限制的,不能让本来出成绩时间小于等于第x天的课程变为出成绩时间大于第x天的课程,因为这样就需要额外使用方式二将它的成绩时间移回第x天,得不偿失)

代码一:

for(;;)

{

sort 排序所有的成绩时间

if (最晚一科出成绩的时间<=x)break;

if (最早一科出成绩的时间<x&&A<B)

  执行方案一

else

  执行方案二

}

但是这样时间复杂度很高,为O(n的3次方),我们注意到第x天前和第x天后后的天数分别具有相同的性质,所以我们可以把他们分别组合起来

如果A<B那么就尽可能多得用方案一,方案一用不了后再用方案二

如果A>B,那么就一直用方案二

代码二:

daysbeforex=SUM{x-b[i]}(x<b[i])

daysafterx=SUM{b[i]-x}(x>b[i])

if (A<B)

{

  if (daysbeforex>daysafterx)

    return A*daysafterx;

  else

    return daysbeforex*A+(daysafterx-daysbeforex)*B;

}

else

  return daysafterx*b;

这样复杂度就降到了O(n的2次方),当然不难发现其实还可以再优化到O(n),只要for遍历一次就可以求出来第i天出成绩所产生的不愉悦度,只要统计出每次成绩时间由大于i变为小于i的天数即可,这就是满分做法,我就不详细列出代码了。

代码三:………………

NOIP2017 d1t1 期末考试