先复习一下 这个题。。。
#include <lastweapon/geometry>
using namespace lastweapon;
using namespace CG;
const int N = 21;
DB dp[N][4], x[N], y[N][4];
int n;
bool ok(int i0, int j0, int i1, int j1) {
Line s(Po(x[i0], y[i0][j0]), Po(x[i1], y[i1][j1]));
FOR(i, i0+1, i1) {
if(Seg(Po(x[i], y[i][0]), Po(x[i], y[i][1])).sgn(s) < 0 &&
Seg(Po(x[i], y[i][2]), Po(x[i], y[i][3])).sgn(s) < 0) return 0;
}
return 1;
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
RD(n); REP(j, 4) y[0][j] = 5;
REP_1(i, n) {
RF(x[i]); REP(j, 4) RF(y[i][j]);
}
x[++n] = 10; REP(j, 4) y[n][j] = 5;
REP_1(i, n) REP(j, 4) dp[i][j] = OO;
FOR(i, 0, n) REP(j, 4) FOR_1(ii, i+1, n) REP(jj, 4) {
if (ok(i, j, ii, jj)) checkMin(dp[ii][jj], dp[i][j] + dist(Po(x[i], y[i][j]), Po(x[ii], y[ii][jj])));
}
printf("%.2f\n", dp[n][0]);
}
然后可以先直接输出 dist(s, t) 怒骗 20 分。。。(因为你数据里肯定也必须有这种类型的数据吧。。。)
#include <lastweapon/geometry>
using namespace lastweapon;
using namespace CG;
const int N = int(2e3) + 9;
struct Rect {
int x0, y0, x1, y1;
void in() {
RD(x0, y0, x1, y1);
}
} R[N];
DB f[N][2]; Po s, t;
int n;
DB gao() {
return dist(s, t);
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
RD(n); REP(i, n) R[i].in(); s.in(); t.in();
printf("%9f\n", gao() / RF());
}
核心的区别就是 vijos 那个题,我可以 O(n3) dp,暴力 check 两点之间的可达性。.而 NOI 这个题,每次只有一段空隙,所以可通过区域是一个不断缩小的扇形。。于是复杂度就 O(n2) 了。
顺便原版 vijos 的那个版本,其实我们也可以用平衡木来维护可通过的区域。。。
回到实现。。孤立的 s 点和 t 点很烦。。而且有很多 corner case。。
我们想办法把 s 和 t 都视为一个退化的矩形。。。。这样我就不用写额外的代码了。
#include <lastweapon/geometry>
using namespace lastweapon;
using namespace CG;
const int N = int(2e3) + 9;
struct Rect {
int x0, y0, x1, y1;
void in() {
RD(x0, y0, x1, y1);
}
} R[N];
DB f[N][2]; int l[N], r[N]; Po s, t;
int n;
bool cmp(const Rect R, int x) {
return R.x1 < x;
}
DB gao() {
int si = lower_bound(R+1, R+n+1, s.x, cmp) - R;
int ti = lower_bound(R+1, R+n+1, t.x, cmp) - R;
if (si > ti) swap(si, ti), swap(s, t);
if (R[si].x1 != s.x) --si;
++ti; if (R[ti].x0 == t.x) ++ti;
R[si].x1 = s.x; R[si].y0 = R[si].y1 = s.y;
R[ti-1].x1 = t.x; R[ti].x0 = t.x; R[ti].y0 = R[ti].y1 = t.y;
FOR(i, si+1, ti) f[i][0] = f[i][1] = OO; f[si][0] = f[si][1] = 0;
FOR(i, si, ti) l[i] = max(R[i].y0, R[i+1].y0), r[i] = min(R[i].y1, R[i+1].y1);
--ti;
#define u f[i][j]
#define v f[ii][jj]
#define w dist(pu, pv)
FOR(i, si, ti) REP(j, 2) {
Po pu(R[i].x1, j ? r[i] : l[i]);
DB ar = PI/2, al = -ar;
//cout << pu << ": " << u << endl;
FOR_1(ii, i+1, ti) REP(jj, 2) {
Po pv(R[ii].x1, jj ? r[ii] : l[ii]);
DB t = atan2(pv.y-pu.y, pv.x-pu.x); if (t > PI) t -= 2*PI;
if (al <= t && t <= ar) checkMin(v, u + w);
if (jj) checkMin(ar, t); else checkMax(al, t);
}
}
return f[ti][0];
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
RD(n); REP_1(i, n) R[i].in(); s.in(); t.in();
printf("%9f\n", gao() / RF());
}




Alca
Amber
Belleve Invis
Chensiting123
Edward_mj
Fotile96
Hlworld
Kuangbin
Liyaos
Lwins
LYPenny
Mato 完整版
Mikeni2006
Mzry
Nagatsuki
Neko13
Oneplus
Rukata
Seter
Sevenkplus
Sevenzero
Shirleycrow
Vfleaking
wangzhpp
Watashi
WJMZBMR
Wywcgs
XadillaX
Yangzhe
三途川玉子
About.me
Vijos
