题解 P5006 【空间复杂度】
一扶苏一
2019-01-10 08:40:29
验题人来发一波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]);
}
```