记录编号 |
216263 |
评测结果 |
AAAAAAAAAWAWWWWWWWWA |
题目名称 |
[国家集训队2011]元素之泉 |
最终得分 |
55 |
用户昵称 |
zhengtn03 |
是否通过 |
未通过 |
代码语言 |
C++ |
运行时间 |
0.130 s |
提交时间 |
2015-12-28 07:27:01 |
内存使用 |
4.71 MiB |
显示代码纯文本
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<sstream>
#include<iomanip>
#include<stdlib.h>
using namespace std;
#define eps 1.0e-8
#define ll long long
#define INF 2000000000
#define PI acos(-1.0)
int zero(double number)
{
if (abs(number) < eps) return 1;
return 0;
}
struct P3
{
double x, y, z; P3()
{
x = 0; y = 0; z = 0;
}
P3(double x1, double y1, double z1)
{
x = x1;
y = y1;
z = z1;
}
void Scan()
{
scanf("%lf%lf%lf", &x, &y, &z);
}
void Print()const
{
printf("%lf %lf %lf\n", x, y, z);
}
double Length()
{
return sqrt(x*x + y*y + z*z);
}
P3 Unit()
{
double d = sqrt(x*x + y*y + z*z);
if (d > 0)
{
x /= d;
y /= d;
z /= d;
}
return *this;
}
}; P3 p[10010];
int operator ==(const P3 &p1, const P3 &p2)
{
return abs(p1.x - p2.x) <= eps && abs(p1.y - p2.y) <= eps && abs(p1.z - p2.z) <= eps;
}
int operator !=(const P3 &p1, const P3 &p2)
{
return abs(p1.x - p2.x) > eps || abs(p1.y - p2.y) > eps || abs(p1.z - p2.z) > eps;
}
P3 Det(const P3 &p1, const P3 &p2)
{
return P3(p1.y*p2.z - p1.z*p2.y, p1.z*p2.x - p1.x*p2.z, p1.x*p2.y - p1.y*p2.x);
}
double Dot(const P3 &p1, const P3 &p2)
{
return p1.x*p2.x + p1.y*p2.y + p1.z*p2.z;
}
P3 operator +(const P3 &p1, const P3 &p2)
{
return P3(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z);
}
P3 operator -(const P3 &p1, const P3 &p2)
{
return P3(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z);
}
P3 operator *(const P3 &p1, double number)
{
return P3(p1.x * number, p1.y * number, p1.z * number);
}
P3 operator *(double number, const P3 &p1)
{
return P3(p1.x * number, p1.y * number, p1.z * number);
}
P3 operator /(const P3 &p1, double number)
{
return P3(p1.x / number, p1.y / number, p1.z / number);
}
double operator /(const P3 &p1, const P3 &p2)
{
if (!zero(p2.x)) return p1.x / p2.x;
else if (!zero(p2.y)) return p1.y / p2.y;
else if (!zero(p2.z)) return p1.z / p2.z;
return 0;
}
P3 operator -(const P3 &p1)
{
return P3(-p1.x, -p1.y, -p1.z);
}
double Dist(const P3 &p1, const P3 &p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y) + (p1.z - p2.z)*(p1.z - p2.z));
}
void swap(P3 &p1, P3 &p2)
{
P3 temp = p1;
p1 = p2;
p2 = temp;
}
int operator <(const P3 &p1, const P3 &p2)
{
if (p1.x != p2.x) return p1.x < p2.x;
if (p1.y != p2.y) return p1.y < p2.y;
return p1.z < p2.z;
}
struct Line3
{
P3 a, b; Line3()
{
}
Line3(P3 a1, P3 b1)
{
a = a1;
b = b1;
}
void Print()
{
a.Print();
b.Print();
}
}; Line3 l[210];
struct Plane3
{
P3 a, b, c;/*逆时针*/ Plane3()
{
}
Plane3(const P3 &p1, const P3 &p2, const P3 &p3)
{
a = p1;
b = p2;
c = p3;
}
void Print()
{
a.Print();
b.Print();
c.Print();
}
P3 NormalVector()const
{
return Det(a - b, b - c);
}
int On(const P3 &p1)const
{
if (zero(Dot(p1 - a, Det(a - b, b - c)))) return 1;
return 0;
}
}; Plane3 s[210];
struct Ball
{
P3 o; double r; Ball()
{
}
int Inside(const P3 &p)
{
return (Dist(p, o) <= r + eps);
}
}; Ball ball[210];
void DrawPoint(P3 p[], int n)
{
printf("ListPointPlot3D[{");
for (int i = 0; i < n - 1; i++)
{
printf("{%lf,%lf,%lf},", p[i].x, p[i].y, p[i].z);
}
printf("{%lf,%lf,%lf}", p[n - 1].x, p[n - 1].y, p[n - 1].z);
printf("}]");
}
void DrawBall(const Ball &ball)
{
printf("ContourPlot3D[");
printf("(x - %lf)^2 + (y - %lf)^2 + (z - %lf)^2 == %lf", ball.o.x, ball.o.y, ball.o.z, ball.r*ball.r);
printf(", { x, %lf, %lf }", ball.o.x - ball.r, ball.o.x + ball.r);
printf(", { y, %lf, %lf }", ball.o.y - ball.r, ball.o.y + ball.r);
printf(", { z, %lf, %lf }", ball.o.z - ball.r, ball.o.z + ball.r);
printf("]\n");
}
void DrawPlane(const Plane3 &s)
{
printf("ListPlot3D[{");
printf("{%lf, %lf, %lf},", s.a.x, s.a.y, s.a.z);
printf("{%lf, %lf, %lf},", s.b.x, s.b.y, s.b.z);
printf("{%lf, %lf, %lf}", s.c.x, s.c.y, s.c.z);
printf("}]\n");
}
void DrawPlane(Plane3 s[], int n)
{
printf("Show[");
for (int i = 0; i < n; i++)
{
DrawPlane(s[i]);
printf(",");
}
printf("PlotRange -> All]\n");
}
int SamaLine(const P3 &p1, const P3 &p2, const P3 &p3)
{
return zero(Det(p2 - p1, p3 - p1).Length());
}
int SamePlane(const P3 &p1, const P3 &p2, const P3 &p3, const P3 &p4)
{
Plane3 s = Plane3(p1, p2, p3);
return zero(Dot(s.NormalVector(), p4 - p1));
}
int SamePlane(const Line3 &l1, const Line3 &l2)
{
return SamePlane(l1.a, l1.b, l2.a, l2.b);
}
//点在平面法线一侧,不包括平面内
int SameDirection(const P3 &p1, const Plane3 &s1)
{
return Dot(s1.NormalVector(), p1 - s1.a) > eps;
}
int Parallel(const P3 &p1, const P3 &p2)
{
return zero(Det(p1, p2).Length());
}
int Parallel(const Line3 &l1, const Line3 &l2)
{
return zero(Det(l1.b - l1.a, l2.b - l2.a).Length());
}
//和法向量垂直,平行或在平面内
int Parallel(const Line3 &l1, const Plane3 &s1)
{
return zero(Dot(l1.b - l1.a, s1.NormalVector()));
}
int Parallel(const P3 &p1, const Plane3 &s1)
{
return zero(Dot(p1, s1.NormalVector()));
}
int Parallel(const Plane3 &s1, const Plane3 &s2)
{
return Parallel(s1.NormalVector(), s2.NormalVector());
}
int Perpendicular(const P3 &p1, const P3 &p2)
{
return zero(Dot(p1, p2));
}
int Perpendicular(const Line3 &l1, const Line3 &l2)
{
return zero(Dot(l1.b - l1.a, l2.b - l2.a));
}
int Perpendicular(const Plane3 &s1, const Plane3 &s2)
{
//return Parallel(s1.NormalVector(), s2);
return Perpendicular(s1.NormalVector(), s2.NormalVector());
}
//平行算不相交
int Connect(const Line3 &l1, const Line3 &l2, P3 &p)
{
if (SamePlane(l1, l2) == 0) return 0;
if (Parallel(l1, l2)) return 0;
double t = Det(l2.a - l1.a, l2.b - l2.a) / Det(l1.b - l1.a, l2.b - l2.a);
p = (l1.b - l1.a)*t + l1.a;
return 1;
}
P3 Connect(const Line3 &l1, const Line3 &l2)
{
P3 ans;
double t = Det(l2.a - l1.a, l2.b - l2.a) / Det(l1.b - l1.a, l2.b - l2.a);
ans = (l1.b - l1.a)*t + l1.a;
return ans;
}
P3 Connect(const Line3 &l1, const Plane3 &s1)
{
P3 ans;
if (Parallel(l1, s1)) return ans;
P3 ret = s1.NormalVector();
double t = Dot(s1.a - l1.a, ret) / Dot(l1.b - l1.a, ret);
ans = l1.a + t*(l1.b - l1.a);
return ans;
}
int Connect(const Line3 &l1, const Plane3 &s1, P3 &p)
{
if (Parallel(l1, s1)) return 0;
P3 ret = s1.NormalVector();
double t = Dot(s1.a - l1.a, ret) / Dot(l1.b - l1.a, ret);
p = l1.a + t*(l1.b - l1.a);
return 1;
}
int Connect(const Plane3 &s1, const Plane3 &s2, Line3 &l1)
{
if (Parallel(s1, s2)) return 0;
P3 p[3];
Line3 l[3];
l[0] = Line3(s1.a, s1.b);
l[1] = Line3(s1.b, s1.c);
l[2] = Line3(s1.c, s1.a);
int pos = 0;
int flag = -1;
for (int i = 0; i < 3; i++)
{
if (Parallel(l[i], s2) == 0)
{
p[pos] = Connect(l[i], s2);
pos++;
}
else flag = i;
}
if (flag == -1)//三条直线都不平行
{
if (p[0] != p[1]) l1 = Line3(p[0], p[1]);
else l1 = Line3(p[1], p[2]);
}
else l1 = Line3(p[0], p[0] + l[flag].b - l[flag].a);
return 1;
}
double Dist(const P3 &p1, const Line3 &l1)
{
double s1 = abs(Det(p1 - l1.b, p1 - l1.a).Length());
return s1 / Dist(l1.a, l1.b);
}
double Dist(const P3 &p1, const Plane3 &s1)
{
P3 ret = s1.NormalVector();
return Dot(p1 - s1.a, ret) / ret.Length();
}
P3 project(const P3 &p1, const P3 &p2)
{
double d2 = (p2.x*p2.x + p2.y*p2.y + p2.z*p2.z);
if (d2 > 0) return Dot(p1, p2) / d2*p2;
else return P3(0, 0, 0);
}
//异面直线公垂线中点
P3 CommonPerpendicular(const Line3 &l1, const Line3 &l2)
{
P3 p1 = l1.b - l1.a;
P3 p2 = l2.b - l2.a;
P3 ret = Det(p1, p2);
Plane3 s1(l1.a, l1.b, l1.a + ret);
Plane3 s2(l2.a, l2.b, l2.a + ret);
P3 ans1 = Connect(l2, s1);
P3 ans2 = Connect(l1, s2);
return (ans1 + ans2) / 2;
}
P3 FootPoint(const P3 &p1, const Line3 &l1)
{
return l1.a + project(p1 - l1.a, l1.b - l1.a);
}
double area(const P3 &p1, const P3 &p2, const P3 &p3)
{
return abs(Det(p2 - p1, p3 - p1).Length()) / 2;
}
double area(const Plane3 &s1)
{
return abs(Det(s1.b - s1.a, s1.c - s1.a).Length()) / 2;
}
bool cmp1(const P3 &p1, const P3 &p2)
{
if (p1.x != p2.x) return p1.x < p2.x;
if (p1.y != p2.y) return p1.y < p2.y;
return p1.z < p2.z;
}
int InsideTriangle(const P3 &p, const Plane3 &s)//包含边界
{
double s1 = area(s.a, s.b, p);
double s2 = area(s.b, s.c, p);
double s3 = area(s.c, s.a, p);
if (abs(s1 + s2 + s3 - area(s.a, s.b, s.c)) > eps) return 0;
return 1;
}
struct Cube
{
double x1, y1, z1, x2, y2, z2;
Cube()
{
}
Cube(double _x1, double _y1, double _z1, double _x2, double _y2, double _z2)
{
x1 = _x1; y1 = _y1; z1 = _z1; x2 = _x2; y2 = _y2; z2 = _z2;
}
double volume()const
{
return (x2 - x1)*(y2 - y1)*(z2 - z1);
}
int in(const Cube &cube)
{
if (cube.x1 + eps >= x1 && cube.x2 <= x2 + eps &&
cube.y1 + eps >= y1 && cube.y2 <= y2 + eps &&
cube.z1 + eps >= z1 && cube.z2 <= z2 + eps)
return 1;
return 0;
}
void Print()const
{
printf("(%lf,%lf,%lf)(%lf,%lf,%lf)\n", x1, y1, z1, x2, y2, z2);
}
}; Cube cube[210];
struct ConvexHull
{
struct cmp
{
bool operator ()(const P3 &x, const P3 &y)
{
return x < y;
};
};
const static int N = 1001;//点数
struct f
{
int a, b, c;
f(int a1, int b1, int c1)
{
a = a1; b = b1; c = c1;
}
};
vector<f> s;
vector<int> valid;
int vist[N][N];
vector<P3> ConvexHullArea2(P3 p[], int n, const P3 &ret)
{
vector<P3> point1;
if (n == 1){ point1.push_back(p[0]); return point1; }
if (n == 2)
{
if (p[0] == p[1])
{
point1.push_back(p[0]); return point1;
}
else
{
point1.push_back(p[0]);
point1.push_back(p[1]); return point1;
}
}
vector<P3> point2;
sort(p, p + n, cmp1);
point1.push_back(p[0]);
point1.push_back(p[1]);
for (int i = 2; i < n; i++)
{
int pos = point1.size() - 1;
while (1)
{
P3 p2 = p[i] - point1[pos];
P3 p1 = point1[pos] - point1[pos - 1];
if (Dot(Det(p1, p2), ret) > 0)
{
point1.push_back(p[i]);
break;
}
else
{
point1.pop_back();
pos--;
if (pos == 0)
{
point1.push_back(p[i]);
break;
}
}
}
}
point1.pop_back();
point2.push_back(p[n - 1]);
point2.push_back(p[n - 2]);
for (int i = n - 3; i >= 0; i--)
{
int pos = point2.size() - 1;
while (1)
{
P3 p2 = p[i] - point2[pos];
P3 p1 = point2[pos] - point2[pos - 1];
if (Dot(Det(p1, p2), ret) > 0)
{
point2.push_back(p[i]);
break;
}
else
{
point2.pop_back();
pos--;
if (pos == 0)
{
point2.push_back(p[i]);
break;
}
}
}
}
point1.insert(point1.end(), point2.begin(), point2.end());//起点和终点是同一点
point1.pop_back();
return point1;
}
void DFS(P3 p[], int i, int j)
{
int number = vist[s[j].b][s[j].a];
if (valid[number])
{
Plane3 tempS = Plane3(p[s[number].a], p[s[number].b], p[s[number].c]);
if (SameDirection(p[i], tempS))
{
valid[number] = 0;
DFS(p, i, number);
}
else
{
Plane3 tempS = Plane3(p[s[j].a], p[s[j].b], p[i]);
f tempF = f(s[j].a, s[j].b, i);
for (int k = 0; k < i; k++)
{
if (tempS.On(p[k]) == 0)//找到不在平面内一点
{
if (SameDirection(p[k], tempS)) swap(tempF.a, tempF.b);//使法线朝外
break;
}
}
s.push_back(tempF);
valid.push_back(1);
vist[tempF.a][tempF.b] = s.size() - 1;
vist[tempF.b][tempF.c] = s.size() - 1;
vist[tempF.c][tempF.a] = s.size() - 1;
}
}
number = vist[s[j].c][s[j].b];
if (valid[number])
{
Plane3 tempS = Plane3(p[s[number].a], p[s[number].b], p[s[number].c]);
if (SameDirection(p[i], tempS))
{
valid[number] = 0;
DFS(p, i, number);
}
else
{
Plane3 tempS = Plane3(p[s[j].b], p[s[j].c], p[i]);
f tempF = f(s[j].b, s[j].c, i);
for (int k = 0; k < i; k++)
{
if (tempS.On(p[k]) == 0)//找到不在平面内一点
{
if (SameDirection(p[k], tempS)) swap(tempF.a, tempF.b);//使法线朝外
break;
}
}
s.push_back(tempF);
valid.push_back(1);
vist[tempF.a][tempF.b] = s.size() - 1;
vist[tempF.b][tempF.c] = s.size() - 1;
vist[tempF.c][tempF.a] = s.size() - 1;
}
}
number = vist[s[j].a][s[j].c];
if (valid[number])
{
Plane3 tempS = Plane3(p[s[number].a], p[s[number].b], p[s[number].c]);
if (SameDirection(p[i], tempS))
{
valid[number] = 0;
DFS(p, i, number);
}
else
{
Plane3 tempS = Plane3(p[s[j].a], p[s[j].c], p[i]);
f tempF = f(s[j].a, s[j].c, i);
for (int k = 0; k < i; k++)
{
if (tempS.On(p[k]) == 0)//找到不在平面内一点
{
if (SameDirection(p[k], tempS)) swap(tempF.a, tempF.b);//使法线朝外
break;
}
}
s.push_back(tempF);
valid.push_back(1);
vist[tempF.a][tempF.b] = s.size() - 1;
vist[tempF.b][tempF.c] = s.size() - 1;
vist[tempF.c][tempF.a] = s.size() - 1;
}
}
}
vector<P3> ConvexHullArea3(P3 p[], int n)
{
vector<P3> ans;
int pos = 1;
for (int i = 1; i < n; i++)
{
if (p[0] != p[i]) swap(p[1], p[i]); pos = 2; break;
}
if (pos != 2){ ans.push_back(p[0]); return ans; }//共点
for (int i = 2; i < n; i++)
{
if (SamaLine(p[0], p[1], p[i]) == 0) swap(p[2], p[i]); pos = 3; break;
}
if (pos != 3)
{
sort(p, p + n, cmp1);
ans.push_back(p[0]);
ans.push_back(p[n - 1]);
return ans;//所有点共线
}
for (int i = 3; i < n; i++)
{
if (SamePlane(p[0], p[1], p[2], p[i]) == 0) swap(p[3], p[i]); pos = 4; break;
}
if (pos != 4)
{
P3 ret;//规定一个平面的方向
ret = Plane3(p[0], p[1], p[2]).NormalVector();
if (zero(ret.z) != 0)
{
if (ret.z < 0) ret = -ret;
}
else if (zero(ret.y) != 0)
{
if (ret.y > 0) ret = -ret;
}
else if (zero(ret.x) != 0)
{
if (ret.x < 0) ret = -ret;
}
ret.Unit();
return ConvexHullArea2(p, n, ret);//调用二维凸包
}
for (int i = 0; i < 4; i++)
{
Plane3 tempS = Plane3(p[(i + 1) % 4], p[(i + 2) % 4], p[(i + 3) % 4]);
f tempF = f((i + 1) % 4, (i + 2) % 4, (i + 3) % 4);
if (SameDirection(p[i], tempS)) swap(tempF.a, tempF.b);//使法线朝外
s.push_back(tempF);
valid.push_back(1);
vist[tempF.a][tempF.b] = i;
vist[tempF.b][tempF.c] = i;
vist[tempF.c][tempF.a] = i;
}
for (int i = 4; i < n; i++)
{
for (int j = 0; j < s.size(); j++)
{
if (valid[j] == 1)//面在外面
{
Plane3 tempS = Plane3(p[s[j].a], p[s[j].b], p[s[j].c]);
if (SameDirection(p[i], tempS))
{
valid[j] = 0;
DFS(p, i, j);
break;
}
}
}
}
set<int> outPoint;
set<int>::iterator ite;
for (int i = 0; i < s.size(); i++)
{
if (valid[i] == 1)
{
outPoint.insert(s[i].a);
outPoint.insert(s[i].b);
outPoint.insert(s[i].c);
}
}
for (ite = outPoint.begin(); ite != outPoint.end(); ite++)
{
ans.push_back(p[*ite]);
}
return ans;
}
}; ConvexHull hull;
double a[10010];
P3 p1[10010];
struct cmp
{
bool operator ()(const P3 &x, const P3 &y)
{
return x < y;
};
};
int main()
{
freopen("nt2011_spring.in", "r", stdin);
freopen("nt2011_spring.out", "w", stdout);
int n, m;
scanf("%d%d", &n, &m);
int ans = 0;
if (m == 1)
{
for (int i = 0; i < n; i++)
{
double temp;
scanf("%lf", &temp);
}
if (n == 1) ans = 0;
else ans = n;
}
else if (m == 2)
{
for (int i = 0; i < n; i++)
{
scanf("%lf", a + i);
double temp;
scanf("%lf", &temp);
}
sort(a, a + n);
if (n == 1) ans = 0;
ans = n - 2;
if (abs(a[0] - a[1]) < eps) ans++;
if (abs(a[n - 1] - a[n - 2]) < eps) ans++;
}
else if (m == 3)
{
map<P3, int, cmp> m;
for (int i = 0; i < n; i++)
{
p[i].Scan();
p[i].z = 0;
m[p[i]]++;
}
sort(p, p + n, cmp1);
int count1 = 0;
p1[count1] = p[0];
count1++;
for (int i = 1; i < n; i++)
{
if (p[i] != p[i - 1])
{
p1[count1] = p[i];
count1++;
}
}
vector<P3> temp = hull.ConvexHullArea2(p1, count1, P3(0, 0, 1));
ans = n - temp.size();
for (int i = 0; i < temp.size(); i++)
{
if (m[temp[i]] != 1) ans++;
}
}
else if (m == 4)
{
map<P3, int, cmp> m;
for (int i = 0; i < n; i++)
{
double temp;
scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].z);
m[p[i]]++;
}
sort(p, p + n, cmp1);
int count1 = 0;
p1[count1] = p[0];
count1++;
for (int i = 1; i < n; i++)
{
if (p[i] != p[i - 1])
{
p1[count1] = p[i];
count1++;
}
}
vector<P3> temp = hull.ConvexHullArea3(p1, count1);
ans = n - temp.size();
for (int i = 0; i < temp.size(); i++)
{
if (m[temp[i]] != 1) ans++;
}
}
printf("%d\n", ans);
return 0;
}