QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#451109#6821. Another A+B ProblemPetroTarnavskyi#TL 0ms0kbC++204.2kb2024-06-22 21:08:422024-06-22 21:08:42

Judging History

你现在查看的是最新测评结果

  • [2024-06-22 21:08:42]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:0kb
  • [2024-06-22 21:08:42]
  • 提交

answer

#include <bits/stdc++.h>

using namespace std;

#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define RFOR(i, a, b) for(int i = (a) - 1; i >= (b); i--)
#define SZ(a) int(a.size())
#define ALL(a) a.begin(), a.end()
#define PB push_back
#define MP make_pair
#define F first
#define S second

typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> PII;
typedef double db;

const db EPS = 1e-9;
const db INF = 1e9;

template<typename T>
void updMin(T& a, T b)
{
	a = min(a, b);
}

struct Pt
{
	db x, y;
	Pt operator+(const Pt& p) const
	{
		return {x + p.x, y + p.y};
	}
	Pt operator-(const Pt& p) const
	{
		return {x - p.x, y - p.y};
	}
	Pt operator*(db d) const
	{
		return {x * d, y * d};
	}
	Pt operator/(db d) const
	{
		return {x / d, y / d};
	}
};

db sq(const Pt& p)
{
	return p.x * p.x + p.y * p.y;
}

db abs(const Pt& p)
{
	return sqrt(sq(p));
}

int sgn(db x)
{
	return (EPS < x) - (x < -EPS);
}

Pt perp(const Pt& p)
{
	return {-p.y, p.x};
}

db dot(const Pt& p, const Pt& q)
{
	return p.x * q.x + p.y * q.y;
}

db cross(const Pt& p, const Pt& q)
{
	return p.x * q.y - p.y * q.x;
}

db orient(const Pt& p, const Pt& q, const Pt& r)
{
	return cross(q - p, r - p) / abs(q - p);
}

ostream& operator<<(ostream& os, const Pt& p)
{
	return os << "(" << p.x << "," << p.y << ")";
}

struct Line
{
	Pt n;
	db c;
	Line(const Pt& p, const Pt& q):
		n(perp(q - p)), c(-dot(n, p)) {}
	db side(const Pt& p) const
	{
		return dot(n, p) + c;
	}
	db sqDist(const Pt& p) const
	{
		return side(p) * side(p) / (db)sq(n);
	}
	Pt proj(const Pt& p) const
	{
		return p - n * side(p) / sq(n);
	}
};

bool inDisk(const Pt& a, const Pt& b, const Pt& p)
{
	return sgn(dot(a - p, b - p)) <= 0;
}

bool onSegment(const Pt& a, const Pt& b, const Pt& p)
{
	return sgn(orient(a, b, p)) == 0 && inDisk(a, b, p);
}

bool properInter(const Pt& a, const Pt& b, const Pt& c, const Pt& d)
{
	db oa = orient(c, d, a);
	db ob = orient(c, d, b);
	db oc = orient(a, b, c);
	db od = orient(a, b, d);
	return sgn(oa) * sgn(ob) == -1 && sgn(oc) * sgn(od) == -1;
}

vector<Pt> circleLine(const Pt& o, db r, const Line& l)
{
	db h2 = r * r - l.sqDist(o);
	if (sgn(h2) == -1)
		return {};
	Pt p = l.proj(o);
	if (sgn(h2) == 0)
		return {p};
	Pt h = perp(l.n) * sqrt(h2) / abs(l.n);
	return {p - h, p + h};
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout << fixed << setprecision(10);
	int n, m, r;
	cin >> n >> m >> r;
	vector<Pt> vertices;
	FOR(i, 0, n)
	{
		db x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		vertices.PB({x1, y1});
		vertices.PB({x2, y1});
		vertices.PB({x2, y2});
		vertices.PB({x1, y2});
	}
	FOR(i, 0, m)
	{
		db x, y;
		cin >> x >> y;
		vertices.PB({x, y});
	}
	db xs, ys, xt, yt;
	cin >> xs >> ys >> xt >> yt;
	vertices.PB({xs, ys});
	vertices.PB({xt, yt});
	int k = SZ(vertices);
	vector dist(k, vector<db>(k, INF));
	auto check = [&](const Pt& p1, const Pt& p2) -> bool
	{
		bool ok = true;
		FOR(l, 0, n)
		{
			FOR(p, 0, 4)
			{
				Pt q1 = vertices[4 * l + p], q2 = vertices[4 * l + (p + 1) % 4];
				ok &= !properInter(p1, p2, q1, q2);
			}
			ok &= !(onSegment(p1, p2, vertices[4 * l]) && onSegment(p1, p2, vertices[4 * l + 2]));
			ok &= !(onSegment(p1, p2, vertices[4 * l + 1]) && onSegment(p1, p2, vertices[4 * l + 3]));
		}
		return ok;
	};
	FOR(i, 0, k)
	{
		FOR(j, 0, k)
		{
			if (i == j)
			{
				dist[i][j] = 0;
				continue;
			}
			Pt p1 = vertices[i], p2 = vertices[j];
			bool blast = 4 * n <= i && i < 4 * n + m;
			if (check(p1, p2))
			{
				db d = abs(p2 - p1);
				if (blast)
					d = max(0.0, d - r);
				updMin(dist[i][j], d);
			}
			if (blast)
			{
				FOR(l, 0, n)
				{
					FOR(p, 0, 4)
					{
						Pt q1 = vertices[4 * l + p], q2 = vertices[4 * l + (p + 1) % 4];
						Line q12(q1, q2);
						vector<Pt> vec = circleLine(p1, r, q12);
						for (const Pt& pt : vec)
						{
							if (onSegment(q1, q2, pt) && check(pt, p2))
							{
								updMin(dist[i][j], abs(p2 - pt));
							}
						}
					}
				}
			}
		}
	}
	FOR(kk, 0, k)
		FOR(i, 0, k)
			FOR(j, 0, k)
				updMin(dist[i][j], dist[i][kk] + dist[kk][j]);
	cout << dist[k - 2][k - 1] << "\n";
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Time Limit Exceeded

input:

40+11=51
PBGPPGGB

output:


result: