链表的折磨 乐观的中考生
作为参加首届全省统一中考的学生,小林同学的压力非常大。每天老师都会布置很多批作业,每批作业具有相同的优先值(不同批的任务的优先值不一样),由若干个不同的任务组成,每个任务都有唯一的编号,小林同学会把每批作业先按照编号顺序整理好,然后按照这批作业的优先值,放入活页夹里。接下来,她将按照任务在活页夹的顺序依次把作业完成。
但近期情况有改变了:妈妈给她生了一个弟弟,所以她要时不时帮妈妈照看一下他。令她欣慰的是:可爱的弟弟非常乖,每次吵闹的时间和程度都是可以预期的。因此她可以确定当前能用于完成作业的最长时间,每项任务的可持续时间(最短时间和最长时间,其中设置最短时间是因为连续的学习时间非常宝贵,所以在预期弟弟会安静较长时间时,她要把时间放在那些工作量较大的任务上),然后按符合条件的任务在活页夹中的顺序来完成。
林同学非常乐观,当她整理完一批作业,或者结束一次工作时,都会找出该批作业的第三个任务或者活页夹中的第三个任务(因为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;
}