链表的折磨 乐观的中考生

作为参加首届全省统一中考的学生,小林同学的压力非常大。每天老师都会布置很多批作业,每批作业具有相同的优先值(不同批的任务的优先值不一样),由若干个不同的任务组成,每个任务都有唯一的编号,小林同学会把每批作业先按照编号顺序整理好,然后按照这批作业的优先值,放入活页夹里。接下来,她将按照任务在活页夹的顺序依次把作业完成。
但近期情况有改变了:妈妈给她生了一个弟弟,所以她要时不时帮妈妈照看一下他。令她欣慰的是:可爱的弟弟非常乖,每次吵闹的时间和程度都是可以预期的。因此她可以确定当前能用于完成作业的最长时间,每项任务的可持续时间(最短时间和最长时间,其中设置最短时间是因为连续的学习时间非常宝贵,所以在预期弟弟会安静较长时间时,她要把时间放在那些工作量较大的任务上),然后按符合条件的任务在活页夹中的顺序来完成。
林同学非常乐观,当她整理完一批作业,或者结束一次工作时,都会找出该批作业的第三个任务或者活页夹中的第三个任务(因为3是她的幸运数字)看一下,如果任务数少于3个,她会愉快地说一声"OK"。
现在要输出林同学看到的任务和她说的"OK"。
输入时,每次输入一行:
(1)如果该行的第一个数字是正数N时,说明新来了一批任务,这批任务由N个任务构成。第二个数字是该批任务的优先值,为不超过10000的正整数,从第三个数字开始的2*N个数字是顺序的N个任务的信息,前面一个是任务号(不超过10000的正整数),后一个是任务的持续时间(不超过200的正整数)。(每批任务在输入时,已经按照编号排好序了,因此不需要考虑按顺序号的从小到大排序过程,只好按任务来到的顺序简单整理好,放进一个小链表就可以了。)。然后再将这批任务根据优先值插入活页夹(大链表)。
(2)如果该行的第一个数字是负数,则说明现在可以做作业了,接下来会输入三个数字,第一个数字是单项任务的最短持续时间mi,第二个数字是单项任务的最长持续时间ma,最后一个数字是本次工作的最长持续时间load.
(3)如果该行的第一个数字是0,则结束。

函数接口定义:

Task* getBatch(int m);   //接收一批任务,该批任务共有m项任务
Task* addBatch(Task *head, Task *h);//将h指向的小链表插入head指向的大链表,并返回新的大链表首指针。
void display(Task *head, int m);//输出第m项任务的信息,或者输出OK
Task* study(Task*head, int mi, int ma, int load);
//mi是本次学习过程中,所学习的各个单项任务的最短持续时间约束,ma是单项任务的最长持续时间约束, load是本次学习过程的最长持续时间

裁判测试程序样例:

#include <iostream>
using namespace std;
struct Task{
    int ID;//任务编号
    int key;//任务优先级
    int load;//任务持续时间
    Task *next;
};

/* 请在这里填写答案 */

void del(Task* head){//删除链表
    if(head==NULL) return;
    del(head->next);
    delete head;
}
const int K=3;//幸运数字
int main(){
    int count, mi, ma, load;
    Task *head=NULL, *h;
    cin>>count;//输入行的第一个数字
    while(count!=0){
        if(count>0){   //新添加count个任务
            h=getBatch(count);//构建链表,并将首指针返回给h
            display(h, K);//显示小链表的第K个任务或输出OK
            head=addBatch(head, h);//将小链表加入大链表,并将首指针返回
        }else{
            cin>>mi>>ma>>load;
            head=study(head, mi, ma, load);
            display(head,K);//显示大链表的第K个任务或输出OK
        }
        cin>>count;		
    }
    del(head);
    return 0;
}

输入样例:

4 12 101 5 102 3 103 6 104 7
2 22 105 12 106 8
1 9 107 9
-1 5 10 25
0

输出样例:

输出时先输出任务号,再输出任务的优先级,最后输出时间。如果没有可输出的任务,则输出“OK”。

103 12 6
OK
OK
105 22 12

说明:
(1)输入:4 12 101 5 102 3 103 6 104 7后,
子链(即小链表)共有四项任务101,102,103和104,其中第三项任务是103, 所以输出它的编号,优先值和时间103 12 6
将子链加入活页夹(大链表)后,活页夹中也是四项任务
(2)输入:2 22 105 12 106 8后
子链中共有两项任务105和106,找不到第三项,所以输出OK。
加入活页夹中,此时活页夹中共有六项任务:101,102,103,104,105,106
(3)输入:1 9 107 9后
子链中共有一项任务,所以输出OK。
加入活页夹中,此时活页夹中共有七项任务,顺序为:107,101,102,103,104,105,106
(4)-1 5 12 25
则顺序完成活页夹中时间在5和12之间的任务,最多持续时间为20
第一项任务107,持续时间为9,符合要求,完成该项任务后,剩余时间为16
第二项任务101, 持续时间为5, 符合要求,完成该项任务后,剩余时间为11 第三项任务102,持续时间为3, 不符合最低持续时间为5的要求,直接忽略。
第四项任务103,持续时间为6,符合要求,完成该项任务后,剩余时间为5。
接下来的任务都没有足够时间完成,所以此时活页夹中剩余四项任务,为:102,104,105,106
此时输出活页夹的第三项任务信息:105 22 12
(5)输入0,结束

链表一直是我的薄弱点,看了朋友的代码思路清晰了许多,但是明明代码一样,我却始终有两个点错误,看了好几遍也debug不出来。所以……以下代码是我那位朋友的,我顶多也就是辅助理解一下下。

//接收一批任务,该批任务共有m项任务
Task* getBatch(int m) {
    Task* head = NULL, * q= NULL, * p;
    int id, key, load;
    cin >> key;
    for (int i = 0; i < m; i++) {
        cin >> id >> load;
        p = new Task;
        p->load = load;
        p->ID = id;
        p->key = key;
        p->next = NULL;
        if (head == NULL) {
            head = p;
        }
        else
        {
            q->next = p;
        }
        q = p;
    }
    return head;
}

//将h指向的小链表插入head指向的大链表,并返回新的大链表首指针。
Task* addBatch(Task* head, Task* h) {
    Task* p = head, * hp = h;
    if (p == NULL) {
        head = h;
        return head;
    }
    else
    {
        while (p->next != NULL)
            p = p->next;
    }
    while (hp->next != NULL)
        hp = hp->next;
    if (h->key <= head->key)
    {
        hp->next = head;
        head = h;
    }//前插
    else if (h->key >= p->key)
    {
        p->next = h;
    }//后插
    else {
        for (Task* i = head; i->next != NULL; i = i->next) {
            if (h->key < i->next->key) {
                hp->next = i->next;
                i->next = h;
                break;
            }
        }
    }//中间插
    return head;
}

//输出第m项任务的信息,或者输出OK
void display(Task* head, int m) {
    Task* p= head;
    for (int i = 1; i < m; ++i) {
        if (p != NULL) 
            p = p->next;
        else 
            break;
    }
    if (p != NULL) 
        cout << p->ID << ' ' << p->key << ' ' << p->load << endl;
    else cout << "OK"<<endl;
}

//mi是本次学习过程中,所学习的各个单项任务的最短持续时间约束,ma是单项任务的最长持续时间约束, load是本次学习过程的最长持续时间
Task* study(Task* head, int mi, int ma, int load) {
    if (NULL == head) return NULL;
    Task* p = head, * del;
    while (p != NULL) {
        if (head->load >= mi && head->load <= ma && load >= head->load) {//头结点满足条件,删除
            load -= head->load;
            del = head;
            head = head->next;
            delete del;
            p = head;
        }
        else if (p->next != NULL) {
            if (p->next->load >= mi && p->next->load <= ma && load >= p->next->load)
            {
                load -= p->next->load;
                del = p->next;
                if (p->next->next != NULL) {
                    p->next = p->next->next;
                    delete del;
                }
                else {
                    p->next = NULL;
                    delete del;
                    break;
                }
            }
            else
                p = p->next;
        }
        else break;
    }
    return head;
}

posted @ 2022-05-24 20:29  尼古拉斯宝莉  阅读(107)  评论(0编辑  收藏  举报