• 贪心算法——赶作业(C++)


    慢慢来,沉稳一点。

    2024年6月18日


    题目描述

            A同学有n份作业要做,每份作业有一个最后期限,如果在最后期限后交作业就会扣分,现在假设完成每份作业都需要一天。A同学想安排作业顺序,把扣分降到最低,请帮他实现。

    输入格式

            包含t个测试用例,第一行是单个整数t。每个测试用例以一个正整数n开头,表示作业的数量,然后是两行;第一行包含n个整数,表示作业的截至日期;下一行包含n个整数,表示作业未完成需要扣的分数。

    输出格式

            输出扣的最少分数即可。

    输入样例:

    2

    3

    3  3  3

    10  5  1

    7

    1 4 6 4 2 4 3

    3 2 1 7 6 5 4

    输出样例:

    0

    5


    题解思路

            贪心法——带惩罚的调度问题

            利用贪心思想,想让扣的分最低,肯定是先做那些扣分最多的作业,尽可能地保持剩下的作业即使没能完成也可以让扣的分最小化,那第一步就是对作业按扣的分数从大到小排序了,那下一步干什么呢?是不是需要确定做作业的顺序了。

            如果你觉得有疑问,不是已经按惩罚大小排序了吗,那先把惩罚最大的做完不就行了?

            NO!!!

            如果你是学生,你一般来说都是什么时候完成作业的呢?

            欸,知道了吧,是不是deadline呢?就算扣分很大,我们依然保持在最后一天能做完就行了。

            贪心的关键就在这:在排序完之后,我们每次都在截至时间或者靠近截至时间的某个时间完成作业就OK了,这样既能保证扣分大的作业顺利完成,扣分小的作业也能尽可能的完成了。


    以上面的第个例子为例:

    作业截至:1 4 6 4 2 4 3

    惩罚分数:3 2 1 7 6 5 4

    1. 按惩罚分数排序得到:

    作业截至:4 2 4 3 1 4 6

    惩罚分数:7 6 5 4 3 2 1

    2. 下面用i表示当前的作业,days数组用于记录那一天做哪一样作业(days初始化为false),ans表示扣分(初始化为0):

    • i = 0时,其截至时间为4,选择在第4天完成该作业,days[4] = true,不用惩罚,ans = 0;
    • i = 1时,其截至时间为2,选择在第2天完成该作业,days[2] = true,不用惩罚,ans = 0;
    • i = 2时,其截至时间为4,第4天已经规划做作业0了,那就提前一天,选择在第3天完成该作业,days[3] = true,不用惩罚,ans = 0;
    • i = 3时,其截至时间为3,第3天已经规划做作业2了,如果提前一天,第二天同样也安排了做作业1,那就提前两天,days[1] = true,不用惩罚,ans = 0;
    • i = 4时,其截至时间为1,从前面看来前四天都安排了任务,尽可能地做扣分大的了,那么当前就不能完成该作业了,需要惩罚,ans = 3;
    • i = 5时,其截至时间为4,和作业4相同情况,没有可以安排的时间了,需要惩罚,ans = 3+2 = 5;
    • i = 6时,其截至时间为6,选择在第6天完成该作业,days[6] = true,不用惩罚,ans = 5;

    代码实现

    1. 定义homework结构体,在结构体里面重载函数完成排序;

    1. struct homework{
    2. int deadline;
    3. int punish;
    4. homework(int deadline, int punish):deadline(deadline), punish(punish) {}
    5. bool operator<(const homework &s) const{
    6. return punish >= s.punish;
    7. }
    8. };

    2. 定义贪心函数getMinLoss;

    1. int getMinLoss(vector &v){
    2. sort(v.begin(), v.end());
    3. int ans = 0;
    4. int flag[100];//确保足够长的时间
    5. int len = v.size();
    6. memset(flag, 0, sizeof(flag));
    7. //将flag定义成vector初始化为0也行
    8. for(int i = 0; i < len; i++){
    9. if(flag[v[i].deadline] == 0){
    10. flag[v[i].deadline] = 1;
    11. }
    12. else{
    13. int tmp = v[i].deadline;
    14. while(flag[tmp]){
    15. tmp--;
    16. }
    17. if(tmp == 0){
    18. ans += v[i].punish;
    19. }
    20. else{
    21. flag[tmp] = 1;
    22. }
    23. }
    24. }
    25. return ans;
    26. }

    3. 完整代码如下:

    1. // 带惩罚的调度问题
    2. #include
    3. #include
    4. #include
    5. #include
    6. using namespace std;
    7. struct homework{
    8. int deadline;
    9. int punish;
    10. homework(int deadline, int punish):deadline(deadline), punish(punish) {}
    11. bool operator<(const homework &s) const{
    12. return punish >= s.punish;
    13. }
    14. };
    15. int getMinLoss(vector &v){
    16. sort(v.begin(), v.end());
    17. int ans = 0;
    18. int flag[100];
    19. int len = v.size();
    20. memset(flag, 0, sizeof(flag));
    21. for(int i = 0; i < len; i++){
    22. if(flag[v[i].deadline] == 0){
    23. flag[v[i].deadline] = 1;
    24. }
    25. else{
    26. int tmp = v[i].deadline;
    27. while(flag[tmp]){
    28. tmp--;
    29. }
    30. if(tmp == 0){
    31. ans += v[i].punish;
    32. }
    33. else{
    34. flag[tmp] = 1;
    35. }
    36. }
    37. }
    38. return ans;
    39. }
    40. int main(){
    41. cout<<"开始输入数据!!!";
    42. int t;
    43. cin>>t;
    44. vector<int> res;
    45. for(int i = 0; i < t; i++){
    46. int n;
    47. cin>>n;
    48. vector v;
    49. vector<int> Deadline;
    50. vector<int> Punish;
    51. // 输入数据
    52. for(int i = 0; i < n; i++){
    53. int deadline;
    54. cin>>deadline;
    55. Deadline.emplace_back(deadline);
    56. }
    57. for(int i = 0; i < n; i++){
    58. int punish;
    59. cin>>punish;
    60. Punish.emplace_back(punish);
    61. }
    62. // 初始化homework
    63. for(int i = 0; i < n; i++){
    64. v.emplace_back(homework(Deadline[i], Punish[i]));
    65. }
    66. // 将每次的结果插入结果集
    67. res.emplace_back(getMinLoss(v));
    68. }
    69. // 打印结果
    70. int count = 1;
    71. for(auto e:res){
    72. cout<<"第"<"次最少扣"<"分"<
    73. count++;
    74. }
    75. return 0;
    76. }
    77. // 2
    78. // 3
    79. // 3 3 3
    80. // 10 5 1
    81. // 7
    82. // 1 4 6 4 2 4 3
    83. // 3 2 1 7 6 5 4
    84. // 0
    85. // 5

    4. 运行结果

  • 相关阅读:
    51单片机仿真软件 Proteus 8 Pro 安装步骤
    论文笔记:RepVGG Making VGG-style ConvNets Great Again
    Spring Data JPA - Web 支持、排序和分页
    项目经理和产品经理,谁更难?
    甘露糖-聚乙二醇-异硫氰基荧光素FITC-PEG-mannose
    项目性能优化—性能优化的指标、目标
    Map集合概述和一般使用
    TypeScript学习01--安装和基本数据类型
    tensorflow1.基础案例2
    cookie、session、token的区别
  • 原文地址:https://blog.csdn.net/m0_73962294/article/details/139785900