题解 P5006 【空间复杂度】

一扶苏一

2019-01-10 08:40:29

Solution

验题人来发一波OOP的写法……其实主要是针对下面的题解对 ``ceil`` 函数的说法进行一些**纠正和辟谣** 首先是C以及C++标准有关函数参数中表达式类型的规定: 如果一个函数的参数是一个表达式,则**先按照表达式的类型转换规定计算出返回值,再将返回值强制转换成函数参数的类型**。 这个规定用在本题的结果是,如果一个函数的参数为 ``double``,而在调用该函数的时候该参数为两个 ``int`` 相除,那么会先按照 ``int`` 做除法的法则计算出答案,再将答案转换成 ``double``,作为函数的参数。 这样在使用 ``ceil`` 函数时就会出现一些问题:我们都知道对于整形做除法的返回值是一个整数,为商的下取整结果。也就是说这个商**已经是一个下取整的整数了**,我们再将它放到 ``ceil`` 函数里面去,相当于对一个整数上取整,当然会得到错误的结果。 举个例子:我们调用 ``ceil(5 / 3)``,会先计算 ``5 / 3 = 1``,按照这个结果将 ``1`` 带入函数,相当于调用 ``ceil(1)``,答案当然是 ``1``,于是就GG了。 考虑我们应该如何避免这个问题:手写取整函数当然是可以的,但是不够优美。我们考虑C/C++对于有关浮点数(``long double``,``double``,``float``)除法的规定:当除数或被除数**至少一个为浮点数**时,先**将除数和被除数都强制转换成浮点型,再做除法**,返回值为一个浮点型。所以我们只要将**被除数强制转换成浮点数**即可。一种优美的写法是 ``1.0 * a / b``。根据乘法的规定,**浮点型和整形做乘法,返回值为浮点型**,而 ``1.0``是一个浮点型,于是被除数 ``1.0 * a`` 变成了一个**浮点型**,根据上面的分析,上式的结果就是一个正常的浮点数了。 还是以 ``ceil(1.0 * 5 / 3)`` 为例,先计算 ``1.0 * 5``,返回值为 ``5.0`` 为一个浮点数,求 ``5.0 / 3``,因为被除数是一个浮点数,所以被转化成于求 ``5.0 / 3.0``,答案即为``1.6666667``,相当于调用 ``ceil(1.6666667)``,答案显然是 ``2``,是正确的。 以上是有关于 ``ceil`` 函数的问题的纠正 有关数据……出题人说已经修复了,我也不清楚有没有锅,反正不要特判出生点就好啦 剩下模拟貌似也没什么好说的qaq ## Code 楼下有OOP写法当然是当然资瓷的辣,这里放一发假的OOP就跑( ```cpp #include <cmath> #include <cstdio> #include <algorithm> const int maxn = 110; char mp[maxn][maxn]; int n, m, px, py, q; struct Character { int HP, ST, DE; int ehp, est, ede; void print() { printf("%d %d %d\n", this->HP, this->ST, this->DE); } void fight() { int x = int(ceil(1.0 * ehp / std::max(1, ST - ede))); this->HP += std::max(1, x * std::max(1, est - DE)); } void update(const char x) { switch (x) { case 'R': { this->HP = std::max(0, this->HP - 10); break; } case 'Q': { this->ST += 5; break; } case 'Y': { this->DE += 5; break; } case 'M': { fight(); break; } } } }; Character my; void mov(const int x); int main() { freopen("mzq.in", "r", stdin); freopen("mzq.out", "w", stdout); scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) { scanf("%s", mp[i] + 1); } scanf("%d%d%d", &my.ehp, &my.est, &my.ede); scanf("%d%d", &px, &py); scanf("%d%d", &my.ST, &my.DE); scanf("%d", &q); int x; while (q--) { scanf("%d", &x); if (x == 1) { my.print(); } else { x = 0; scanf("%d", &x); mov(x); } } return 0; } void mov(const int x) { switch (x) { case 1: { --py; break; } case 2: { ++py; break; } case 3: { --px; break; } case 4: { ++px; break; } default: { puts("I AK IOI"); break; } }; my.update(mp[px][py]); } ```