diff --git a/content/posts/bj_homework.md b/content/posts/bj_homework.md index 10fb732..b3fd7f9 100644 --- a/content/posts/bj_homework.md +++ b/content/posts/bj_homework.md @@ -2696,6 +2696,568 @@ int main(void) { 计算100!+50!的结果为 ![](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/1201Yr6K7cV6b3Kf.png) +## 第七次作业 +### 第一题 +> 声明一个基类Shape,在此基础上派生出Rectangle和Circle,二者都有GetArea()函数计算对象的面积。使用Rectangle类创建一个派生类Square。 +本题考察类的派生和继承,类的派生和继承是面向对象编程中的重要特性之一,这使得我们可以复用大量代码,进而快速构建出相应的应用程序。需要注意的是子类在实现构造函数时也要显式的声明对应的父类构造函数,以保证在创建一个对象时对象的值没有歧义。根据题意得到的代码如下 +```cpp +#include +#include +#include + +using namespace std; + +class Shape { +public: + int width; + int height; + float radius; + Shape(); + Shape(Shape &&) = default; + Shape(const Shape &) = default; + ~Shape(); + +private: +}; + +Shape::Shape() {} + +Shape::~Shape() {} + +// 矩形 +class Rectangle : public Shape { +public: + Rectangle(int x, int y) { + width = x; + height = y; + } + int GetArea() { return width * height; } +}; + +// 圆 +class Circle : public Shape { +public: + float GetArea() { return M_PI * radius * radius; } +}; + +// 正方形 +class Square : public Rectangle { +public: + Square(int x); +}; + +Square::Square(int x) : Rectangle(x, x) {} + +int main(int argc, char *argv[]) { return 0; } + +``` +### 第二题 +> 声明一个object类,有数据成员weight及相应得存取操作函数,由此派生出box类,增加数据成员height和width及相应得存取操作函数,声明一个box对象,观察构造函数和析构函数的调用顺序。 +本题主要观察父类和子类的构造函数和析构函数的调用顺序,代码如下 +```cpp +#include +#include +#include + +using namespace std; + +// Object基类 +class Object { +public: + Object() { cout << "调用Object构造函数" << endl; } + ~Object() { cout << "调用Object析构函数" << endl; } + float weight; + float get_weight() { return weight; } + void set_weight(float x) { weight = x; } +}; + +// 派生类Box +class Box : public Object { +public: + Box() { cout << "调用Box构造函数" << endl; } + ~Box() { cout << "调用Box析构函数" << endl; } + float height; + float width; + float get_height() { return height; } + void set_height(float x) { height = x; } + float get_width() { return width; } + void set_width(float x) { width = x; } +}; + +int main(int argc, char *argv[]) { + Box abox; + return 0; +} + +``` +运行结果如下 +![](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/1205DAu0fVxPPGDR.png) + +### 第三题 +> 声明一个基类BaseClass,从它派生出类DerivedCalss,BaseClass有成员fn1()、fn2(),DerivedClass也有成员函数fn1()、fn2()。在主函数中声明DerivedClass,分别用DerivedClass的对象以及BaseClass和DerivedClass的指针来调用fn1()、fn2(),观察运行结果。 +根据题目含义,声明一个类DerivedClass的对象,然后将其指针强转为基类的指针调用对应的函数,代码如下 +```cpp +#include +#include +#include +#include + +using namespace std; + +class BaseClass { +public: + void fn1() { cout << "Base fn1" << endl; } + void fn2() { cout << "Base fn2" << endl; } +}; + +class DerivedClass : public BaseClass { +public: + void fn1() { cout << "Derived fn1" << endl; } + void fn2() { cout << "Derived fn2" << endl; } +}; + +int main(int argc, char *argv[]) { + DerivedClass aclass; + aclass.fn1(); + aclass.fn2(); + // 用派生类指针调用函数 + DerivedClass *point = &aclass; + point->fn1(); + point->fn2(); + // 转换成父类指针调用函数 + BaseClass *point1 = (BaseClass *)point; + point1->fn1(); + point1->fn2(); + + return 0; +} + +``` +运行结果如下 + +![](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/1205bBimEzZWoPAx.png) + +可见可以正常调用对应的函数,但是并非总是如此,如果父类和子类中对应的成员函数为虚函数的话,子类指针强转成父类指针,使用这个父类指针调用成员函数,本来是应该调用父类自己的成员函数的,但由于子类的同名成员函数为虚函数(父类的对应成员函数标为虚函数了),强转失效了,调用的还是子类的成员函数。即强转后的指针在调用虚函数时失效,其他情况正常。 + +### 第四题 +> 仿照示例程序08_05,用数组实现线性表类array,从array中派生子类stack和queue,实现出栈、入栈、出队列、入队列等操作。 + +代码如下: + +```cpp +#include +#include +#include +#include + +using namespace std; + +class Array { +public: + // length记录数组长度,now记录当前访问的数组下标,head用于访问数组 + int length; + int now; + int *head; + Array() { + length = 100; + now = 0; + head = new int[length]; + } + // 向数组尾部增加元素,若数组长度不够则申请一个二倍长度的新数组并将head设为新数组的头部 + void in(int number) { + if (now < length) { + head[now] = number; + now++; + } else { + length = 2 * length; + int *newhead = new int[length]; + for (int i = 0; i < now; i++) { + newhead[i] = head[i]; + } + delete head; + head = newhead; + newhead[now] = number; + now++; + } + } +}; + +class stack : public Array { + int out() { + // 拿出最后一个数据,将访问下标减一 + if (now >= 0) { + return head[now]; + now--; + } else { + cout << "stack is empty!!" << endl; + return -1; + } + } + ~stack() { delete head; } +}; + +class queue : public Array { +public: + int begin; + int out() { + if (begin >= now) { + cout << "queue empty!!" << endl; + return -1; + } else { + // 若剩余的queue长度较小则将数据重新移至数组开头 + if ((now - begin) <= length / 4 && begin >= length / 4) { + for (int i = 0; i < (now - begin); i++) { + head[i] = head[begin + i]; + } + begin = 0; + } + // 拿出最开头的数据,符合先入先出的特性 + int point = begin; + begin++; + return head[point]; + } + } + queue() { begin = 0; } +}; +``` +### 编程题#2 +魔兽世界二:装备 +描述 +魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。两个司令部之间是依次排列的若干城市。 +红司令部,City 1,City 2,……,City n,蓝司令部 +两军的司令部都会制造武士。武士一共有 dragon 、ninja、iceman、lion、wolf 五种。每种武士都有编号、生命值这两种属性。 +有的武士可以拥有武器。武器有三种,sword, bomb,和arrow,编号分别为0,1,2。 +双方的武士编号都是从1开始计算。红方制造出来的第 n 个武士,编号就是n。同样,蓝方制造出来的第 n 个武士,编号也是n。 +不同的武士有不同的特点。 +dragon 可以拥有一件武器。编号为n的dragon降生时即获得编号为 n%3 的武器。dragon还有"士气"这个属性,是个浮点数,其值为它降生后其司令部剩余生命元的数量除以造dragon所需的生命元数量。 +ninjia可以拥有两件武器。编号为n的ninjia降生时即获得编号为 n%3 和 (n+1)%3的武器。 +iceman有一件武器。编号为n的iceman降生时即获得编号为 n%3 的武器。 +lion 有"忠诚度"这个属性,其值等于它降生后其司令部剩余生命元的数目。 +wolf没特点。 +请注意,在以后的题目里,武士的士气,生命值,忠诚度在其生存期间都可能发生变化,都有作用,武士手中的武器随着使用攻击力也会发生变化。 +武士在刚降生的时候有一个生命值。 +在每个整点,双方的司令部中各有一个武士降生。 +红方司令部按照 iceman、lion、wolf、ninja、dragon 的顺序循环制造武士。 +蓝方司令部按照 lion、dragon、ninja、iceman、wolf 的顺序循环制造武士。 +制造武士需要生命元。 +制造一个初始生命值为 m 的武士,司令部中的生命元就要减少 m 个。 +如果司令部中的生命元不足以制造某个按顺序应该制造的武士,那么司令部就试图制造下一个。如果所有武士都不能制造了,则司令部停止制造武士。 +给定一个时间,和双方司令部的初始生命元数目,要求你将从0点0分开始到双方司令部停止制造武士为止的所有事件按顺序输出。 +一共有两种事件,其对应的输出样例如下: +1) 武士降生 +输出样例: 004 blue lion 5 born with strength 5,2 lion in red headquarter +表示在 4点整,编号为5的蓝魔lion武士降生,它降生时生命值为5,降生后蓝魔司令部里共有2个lion武士。(为简单起见,不考虑单词的复数形式)注意,每制造出一个新的武士,都要输出此时司令部里共有多少个该种武士。 +如果造出的是dragon,那么还要输出一行,例: +It has a arrow,and it's morale is 23.34 +表示该dragon降生时得到了arrow,其士气是23.34(为简单起见,本题中arrow前面的冠词用a,不用an,士气精确到小数点后面2位,四舍五入) +如果造出的是ninjia,那么还要输出一行,例: +It has a bomb and a arrow +表示该ninjia降生时得到了bomb和arrow。 +如果造出的是iceman,那么还要输出一行,例: +It has a sword +表示该iceman降生时得到了sword。 +如果造出的是lion,那么还要输出一行,例: +It's loyalty is 24 +表示该lion降生时的忠诚度是24。 +2) 司令部停止制造武士 +输出样例: 010 red headquarter stops making warriors +表示在 10点整,红方司令部停止制造武士 +输出事件时: +首先按时间顺序输出; +同一时间发生的事件,先输出红司令部的,再输出蓝司令部的。 +输入 +第一行是一个整数,代表测试数据组数。 +每组测试数据共两行。 +第一行,一个整数M。其含义为: 每个司令部一开始都有M个生命元( 1 <= M <= 10000) +第二行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的初始生命值。它们都大于0小于等于10000 +输出 +对每组测试数据,要求输出从0时0分开始,到双方司令部都停止制造武士为止的所有事件。 +对每组测试数据,首先输出"Case:n" n是测试数据的编号,从1开始 +接下来按恰当的顺序和格式输出所有事件。每个事件都以事件发生的时间开头,时间以小时为单位,有三位。 +样例输入 +1 +20 +3 4 5 6 7 +样例输出 +Case:1 +000 red iceman 1 born with strength 5,1 iceman in red headquarter +It has a bomb +000 blue lion 1 born with strength 6,1 lion in blue headquarter +It's loyalty is 14 +001 red lion 2 born with strength 6,1 lion in red headquarter +It's loyalty is 9 +001 blue dragon 2 born with strength 3,1 dragon in blue headquarter +It has a arrow,and it's morale is 3.67 +002 red wolf 3 born with strength 7,1 wolf in red headquarter +002 blue ninja 3 born with strength 4,1 ninja in blue headquarter +It has a sword and a bomb +003 red headquarter stops making warriors +003 blue iceman 4 born with strength 5,1 iceman in blue headquarter +It has a bomb +004 blue headquarter stops making warriors + +本题是第一次的扩展,加入了装备和各类战士的诸多属性,可以用派生类给各类战士赋予各种独有的属性。在记录各个司令部拥有的战士时,可以直接使用空指针指代不同的战士类,因为指针的长度是固定的,故这样做并不会导致错误,只需要在使用时强转为对应类的指针即可,这样访问对应类的对象并不会产生内存错误。 +代码如下 +```cpp +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +// 构造战士信息哈希表 +map warriors; +vector warrior_name = {"dragon", "ninja", "iceman", "lion", "wolf"}; +vector tool = {"sword", "bomb", "arrow"}; + +class own_warrior { +public: + int number; + int life_value; + // 表示是否拥有武器 + int has_tool; + vector tools; + void metamake(int life, int warrior_num) { + number = warrior_num; + life_value = life; + } +}; + +class dragon : public own_warrior { +public: + // 士气 + float morale; + void make(int life, int warrior_num, int meta_life, string color, int size) { + metamake(life, warrior_num); + has_tool = true; + int tool_num = warrior_num % 3; + tools.push_back(tool_num); + morale = (float)meta_life / (float)life; + cout << color << " " + << "dragon " << warrior_num << " born with strength " << life << "," + << size << " " + << "dragon" + << " in " << color << " headquarter" << endl; + cout << "It has a " << tool[tool_num] + << ",and it's morale is " + // 设定小数精度 + << setprecision(3) << morale << endl; + } +}; + +class lion : public own_warrior { +public: + // 忠诚度 + int loyalty; + // 制造战士的函数,各个战士的该函数均为此用处 + void make(int life, int warrior_num, int meta_life, string color, int size) { + metamake(life, warrior_num); + loyalty = meta_life; + cout << color << " " + << "lion " << warrior_num << " born with strength " << life << "," + << size << " " + << "lion" + << " in " << color << " headquarter" << endl; + cout << "It's loyalty is " << loyalty << endl; + } +}; + +class ninja : public own_warrior { +public: + void make(int life, int warrior_num, int meta_life, string color, int size) { + metamake(life, warrior_num); + has_tool = true; + tools.push_back(warrior_num % 3); + tools.push_back((warrior_num + 1) % 3); + cout << color << " " + << "ninja " << warrior_num << " born with strength " << life << "," + << size << " " + << "ninja" + << " in " << color << " headquarter" << endl; + cout << "It has a " << tool[warrior_num % 3] << " and a " + << tool[(warrior_num + 1) % 3] << endl; + } +}; + +class iceman : public own_warrior { +public: + void make(int life, int warrior_num, int meta_life, string color, int size) { + metamake(life, warrior_num); + has_tool = true; + tools.push_back(warrior_num % 3); + cout << color << " " + << "iceman " << warrior_num << " born with strength " << life << "," + << size << " " + << "iceman" + << " in " << color << " headquarter" << endl; + cout << "It has a " << tool[warrior_num % 3] << endl; + } +}; + +class wolf : public own_warrior { +public: + void make(int life, int warrior_num, int meta_life, string color, int size) { + metamake(life, warrior_num); + cout << color << " " + << "wolf " << warrior_num << " born with strength " << life << "," + << size << " " + << "wolf" + << " in " << color << " headquarter" << endl; + } +}; + +struct warrior { + string name; + int life_value; +}; + +// 司令部类 +class headquarter { +public: + int meta_life; + vector order; + int warrior_now; + bool over; + string color; + int warrior_num; + map *> warrior_info; + headquarter(int, vector, string); + headquarter(headquarter &&) = default; + headquarter(const headquarter &) = default; + headquarter &operator=(headquarter &&) = default; + headquarter &operator=(const headquarter &) = default; + ~headquarter(); + void make_warrior(int); + void judge_make(); + +private: +}; + +// 构造函数,初始化生命元和战士信息 +headquarter::headquarter(int life, vector my_order, string my_color) { + meta_life = life; + order = my_order; + color = my_color; + warrior_num = 1; + over = false; + warrior_now = 0; + for (int i = 0; i < warrior_name.size(); i++) { + vector *temp_vector = new vector; + warrior_info.insert(make_pair(warrior_name[i], temp_vector)); + } +} + +headquarter::~headquarter() {} + +// 制造战士 +void headquarter::make_warrior(int warr_now) { + int life_value = warriors[order[warr_now]]->life_value; + string name = warriors[order[warr_now]]->name; + meta_life -= life_value; + // 为新战士分配内存空间放入对应的map中 + if (name == "dragon") { + dragon *newdragon = new dragon; + warrior_info[name]->push_back(newdragon); + newdragon->make(life_value, warrior_num, meta_life, color, + warrior_info[name]->size()); + } else if (name == "ninja") { + ninja *newninja = new ninja; + warrior_info[name]->push_back(newninja); + newninja->make(life_value, warrior_num, meta_life, color, + warrior_info[name]->size()); + } else if (name == "iceman") { + iceman *newiceman = new iceman; + warrior_info[name]->push_back(newiceman); + newiceman->make(life_value, warrior_num, meta_life, color, + warrior_info[name]->size()); + } else if (name == "lion") { + lion *newlion = new lion; + warrior_info[name]->push_back(newlion); + newlion->make(life_value, warrior_num, meta_life, color, + warrior_info[name]->size()); + } else if (name == "wolf") { + wolf *newwolf = new wolf; + warrior_info[name]->push_back(newwolf); + newwolf->make(life_value, warrior_num, meta_life, color, + warrior_info[name]->size()); + } + warrior_num++; + warrior_now = (warr_now + 1) % (warriors.size()); + // cout << warriors.size() << " " << warrior_now << endl; + return; +} + +// 判能否制造下一个战士,不能则继续制造下一个,直到都不能则结束. +void headquarter::judge_make() { + if (warriors[order[warrior_now]]->life_value <= meta_life) { + make_warrior(warrior_now); + return; + } else { + for (int i = 1; i < warriors.size(); i++) { + if (warriors[order[(warrior_now + i) % warriors.size()]]->life_value <= + meta_life) { + warrior_now = (warrior_now + i) % warriors.size(); + make_warrior(warrior_now); + return; + } + } + over = true; + cout << color << " headquarter stops making warriors" << endl; + return; + } +} + +int main(int argc, char *argv[]) { + int case_no = 0; + int length = 5; + vector red_order = {2, 3, 4, 1, 0}; + vector blue_order = {3, 0, 1, 2, 4}; + //处理每组数据 + while (cin >> case_no) { + int time = 0; + int case_life = 20; + // 读入司令部的元生命值 + cin >> case_life; + warriors.clear(); + // 读入各个战士的生命值 + for (int i = 0; i < length; i++) { + int wa_life = 0; + cin >> wa_life; + struct warrior *new_warrior = new struct warrior; + new_warrior->life_value = wa_life; + new_warrior->name = warrior_name[i]; + warriors.insert(make_pair(i, new_warrior)); + } + headquarter *red_headquarter = new headquarter(case_life, red_order, "red"); + headquarter *blue_headquarter = + new headquarter(case_life, blue_order, "blue"); + cout << "Case:" << case_no << endl; + while (!red_headquarter->over || !blue_headquarter->over) { + if (!red_headquarter->over) { + printf("%03d ", time); + red_headquarter->judge_make(); + } + if (!blue_headquarter->over) { + printf("%03d ", time); + blue_headquarter->judge_make(); + } + time++; + } + } + return 0; +} +``` + +运行得到的结果为 +![](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/1206FQM7IFtpD7S4.png) + + +