【紫书 第五章 习题5-6】
题目比较水,总体做得还算顺利。
算法概述:如果图是对称的,那么 y 坐标相同的点归为一组,第 i 组的点的横坐标的和记为 ∑i ,点的个数记为 si ,则
∑i / si = x0(常数)①
x0 由最左侧点的横坐标与最右侧点的横坐标相加取平均确定。
即相同纵坐标的点的横坐标的和的平均值为 x0,那么对称轴就是 x = x0 。
AC代码0:(10 ms或20 ms)
提交了10次,5次是20 ms,5次是10 ms。也许是因为map里面套个vector再套个pair使得运行速率有所降低。
记映射 f:y0→{(x, y)|y = y0},即自变量为纵坐标 y0 ,因变量为数组,包含全部纵坐标为 y0 的点。cur 为当前输入的点,emptyvec 为空白变长数组vector。
输入完毕后判定 f 中每一项映射代表的点组是否符合式①。为了避免精度问题,避免了使用小数。原本我做的时候是将求得的和统一乘以10再除以si(整数点的对称轴出现小数,小数部分也只可能是.5,乘以10就是小数点右移一位)。不过根据https://blog.csdn.net/acvay/article/details/43015507 等文章,改成了乘以2。因为编译器可能将乘以2或整除2优化为二进制移位运算,加快乘法的运算速率。
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<vector>
#pragma warning(disable:4996)
using namespace std;
map<short, vector<pair<short, short>>> f; pair<short, short> cur;
map<short, vector<pair<short, short>>>::iterator it, I; short XL, XR;
vector<pair<short, short>> emptyvec; int s, sum, x0_2x; bool verdict;
int main() {
//freopen("o.txt", "w", stdout);
unsigned int t; unsigned short n; scanf("%u", &t);
for (unsigned int i = 0; i < t; ++i) {
scanf("%hu", &n); f.clear(); XL = 32767, XR = -32767;
for (unsigned short j = 0; j < n; ++j) {
scanf("%hd%hd", &cur.first, &cur.second);
if (cur.first < XL)XL = cur.first; if (cur.first > XR)XR = cur.first;
it = f.find(cur.second);
switch (it == f.end()) {
case true:f.emplace(cur.second, emptyvec);
f[cur.second].emplace_back(cur); break;
case false:(*it)