之前研究性学习写了这道题。。然而写论文的时候并没有做233,然后现在AC后发现论文里的好像就写错了。。
以下是以前写的粗略的题解。
孩子们的游戏Hotter Colder的游戏规则:A在B在房间内藏了什么东西的时候离开房间,到(0,0)并且访问房间内其他位置。当A到了一个新未知,如果新位置相对于原来的位置更近,则B会说"Hotter",更远"Colder",不变"Same"。你将获得B每次说"Hotter","Colder"或"Same"的信息,同时包含A的位置。求每次信息更新后房间的可能有效区域。如果信息矛盾,面积为0。例如:(0,0)->(10,10): Colder, 面积50; ->(10,0): Hotter, 面积37.5; ->(0,0): Colder, 面积12.5; ->(10,10) Hotter, 面积0.
显然,对于一次坐标移动,比如(0,0)->(10,10)靠的更远,可以理解为要找的东西的坐标(x,y)满足:。即直线是直线l(过点(0,0)和(10,10))的中垂线。对于每次坐标移动我们都建立一个约束,那么可行域面积就是我们要求的。当然如果约束矛盾可行域面积就为0。我们利用半平面交解决该问题。
对于一次移动,其向量的法向量为逆时针旋转90°后的向量,此时的面积就是这些法向量左手半平面交的面积,然后套模板。SAME的话因为点在中垂线上,所以面积就为0了。我就随便加了个向量把结果卡成0了。。挺懒的233。
话说O(n^2)的算法对于这道题好像很优越啊,可惜不会233。
之前竟然贴成错误的代码了。。
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 3333;
struct Point {
double x, y;
Point(){}
Point(double _x, double _y) : x(_x), y(_y) {}
Point operator +(const Point &b) const { return Point(x + b.x, y + b.y); }
Point operator -(const Point &b) const { return Point(x - b.x, y - b.y); }
double operator *(const Point &b) const { return x * b.y - y * b.x; }
Point operator *(double b) const { return Point(b * x, b * y); }
Point normal() { return Point(-y, x); }
} p[N], poly[N];
struct Line {
Point x, v;
double ang;
Line(){}
Line(const Point &_x, const Point &_v) : x(_x), v(_v), ang(atan2(_v.y, _v.x)) { }
bool operator <(const Line &b) const {
if (ang == b.ang) return v * (b.x - x) < 0; // 极角相等时,这么算的叉积表示a在b的左边时返回Line a < b,unique的时候就会选择a而丢掉b。
return ang < b.ang;
}
bool operator ==(const Line &b) const { return ang == b.ang; }
Point intersection(const Line &b) {
Point u = x - b.x;
double t = (b.v * u) / (v * b.v); // 画了图才知道这么写的意思。。
return x + v * t;
}
};
vector<Line> lines;
bool right(const Point &p, const Line &l) {
return l.v * (p - l.x) <= 0;
}
int half_plane_intersection(vector<Line> l, Point poly[]) {
static Line q[N];
sort(l.begin(), l.end());
vector<Line>::iterator end = unique(l.begin(), l.end())++, it = l.begin();
int f = 1, r = 0, m = 0;
q[++r] = *it++; q[++r] = *it++;
while (it != end) {
while (f < r && right(q[r].intersection(q[r - 1]), *it)) r--;
while (f < r && right(q[f].intersection(q[f + 1]), *it)) f++;
q[++r] = *it++;
}
while (f < r && right(q[r].intersection(q[r - 1]), q[f])) r--; // 还要处理首尾
while (f < r && right(q[f].intersection(q[f + 1]), q[r])) f++;
q[r + 1] = q[f];
for (int i = f; i <= r; i++)
poly[++m] = q[i].intersection(q[i + 1]);
return m;
}
double calc_area(Point poly[], int m) {
double ans = 0;
if (m <= 2) return ans;
poly[m + 1] = poly[1];
for (int i = 1; i <= m; i++)
ans += poly[i] * poly[i + 1];
return fabs(ans) / 2;
}
int main() {
char op[10];
p[0] = Point(0, 0);
lines.push_back(Line(Point(0, 0), Point(0, -1)));
lines.push_back(Line(Point(0, 0), Point(1, 0)));
lines.push_back(Line(Point(10, 10), Point(0, 1)));
lines.push_back(Line(Point(10, 10), Point(-1, 0)));
for(int j = 1; scanf("%lf%lf%s", &p[j].x, &p[j].y, op) != EOF; j++) {
if (op[0] == 'S') lines.push_back(Line(Point(0, 0), Point(0, 1)));
lines.push_back(Line((p[j] + p[j - 1]) * 0.5, (p[j] - p[j - 1]).normal() * (op[0] == 'H' ? -1 : 1)));
int m = half_plane_intersection(lines, poly);
printf("%.2lf\n", calc_area(poly, m));
}
return 0;
}
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3004 | Accepted: 1213 |
Description
Input
Output
Sample Input
10.0 10.0 Colder 10.0 0.0 Hotter 0.0 0.0 Colder 10.0 10.0 Hotter
Sample Output
50.00 37.50 12.50 0.00