【LOJ】#2443. 「NOI2011」智能车比赛
题解
显然是个\(n^2\)的dp
我们要找每个点不穿过非赛道区域能到达哪些区域的交点
可以通过控制两条向量负责最靠下的上边界,和最靠上的下边界,检查当前点在不在这两条向量之间即可,对于每个点可以\(O(n)\)求出来哪些点是可以到达的
之后dp即可
注意判断S点所在区域的时候需要找靠后的那个区域……
代码
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <queue> #include <cmath> #define enter putchar('\n') #define space putchar(' ') #define mp make_pair #define pb push_back #define fi first #define se second #define eps 1e-7 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {putchar('-');x = -x;} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N; struct Point { db x,y; Point() {} Point(db _x,db _y) { x = _x;y = _y; } friend Point operator + (const Point &a,const Point &b) { return Point(a.x + b.x,a.y + b.y); } friend Point operator - (const Point &a,const Point &b) { return Point(a.x - b.x,a.y - b.y); } friend Point operator * (const Point &a,const db d) { return Point(a.x * d,a.y * d); } friend Point operator / (const Point &a,const db d) { return Point(a.x / d,a.y / d); } friend db operator * (const Point &a,const Point &b) { return a.x * b.y - a.y * b.x; } }S,T,U[2005],D[2005],pos[2005][2]; db dis(Point a,Point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } db v,ans,dp[2005][2]; bool vis[2005][2]; void Init() { read(N); for(int i = 1 ; i <= N ; ++i) { scanf("%lf%lf%lf%lf",&D[i].x,&D[i].y,&U[i].x,&U[i].y); } scanf("%lf%lf",&S.x,&S.y); scanf("%lf%lf",&T.x,&T.y); scanf("%lf",&v); if(S.x > T.x) swap(S,T); for(int i = 2 ; i <= N ; ++i) { pos[i][0] = Point(D[i].x,max(D[i].y,D[i - 1].y)); pos[i][1] = Point(D[i].x,min(U[i].y,U[i - 1].y)); } } db dfs(int p,int c) { if(vis[p]放假了真是颓啊QwQ[c]) return dp[p][c]; vis[p][c] = 1; Point M = pos[p][c]; if((T.x >= D[p].x && T.x < U[p].x) || (p == N)) return dp[p][c] = dis(M,T); Point Up = pos[p + 1][1] - M,Dw = pos[p + 1][0] - M; dp[p][c] = dfs(p + 1,1) + dis(M,pos[p + 1][1]); dp[p][c] = min(dp[p][c],dfs(p + 1,0) + dis(M,pos[p + 1][0])); for(int i = p + 2; i <= N ; ++i) { if(D[i].x > T.x) break; if(Dw * (pos[i][0] - M) >= 0 && (pos[i][0] - M) * Up >= 0) { dp[p][c] = min(dp[p][c],dfs(i,0) + dis(M,pos[i][0])); } if(Dw * (pos[i][1] - M) >= 0 && (pos[i][1] - M) * Up >= 0) { dp[p][c] = min(dp[p][c],dfs(i,1) + dis(M,pos[i][1])); } if(Dw * (pos[i][0] - M) >= 0) Dw = pos[i][0] - M; if((pos[i][1] - M) * Up >= 0) Up = pos[i][1] - M; } if(Dw * (T - M) >= 0 && (T - M) * Up >= 0) { return dp[p][c] = dis(M,T); } return dp[p][c]; } void Solve() { for(int i = 1 ; i <= N ; ++i) { if(U[i].x <= S.x) continue; pos[i][0] = S; ans = dfs(i,0); break; } if(ans == 0) ans = dis(S,T); printf("%.6lf\n",ans / v); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); }
- [bzoj2433][Noi2011]智能车比赛
- 【DP】[NOI2011]智能车比赛
- ★【视野动态规划】【NOI2011】智能车比赛
- NOI2011 智能车比赛
- 【BZOJ 2433】[Noi2011]智能车比赛
- 【bzoj 2433】【NOI 2011】 智能车比赛 题意&题解&代码(C++)
- noi 2011 智能车比赛
- 2433: [Noi2011]智能车比赛 - BZOJ
- 【bzoj 2433】【NOI 2011 D1T2】 智能车比赛 想法乱搞+暴力
- [NOI2011 智能车比赛]
- 【LOJ】#2445. 「NOI2011」道路修建
- 【LOJ】#2446. 「NOI2011」 NOI 嘉年华
- 【LOJ】#2447. 「NOI2011」兔兔与蛋蛋的游戏
- [NOI2011]智能车比赛(计算几何+动态规划)
- [BZOJ 2433][NOI 2011]智能车比赛(计算几何+动态规划)
- bzoj 2433 [Noi2011]智能车比赛 [计算几何+spfa]
- Noi2011 : 智能车比赛
- 【dfs序+AC自动机+树状数组】BZOJ2434-[Noi2011]阿狸的打字机
- [BZOJ 2435][NOI 2011]道路修建
- [NOI2011]Noi嘉年华(动态规划及单调性优化)