【HDU】5817 Ice Walls【极角排序+树状数组+最短路】
来源:互联网 发布:男士护肤国产品牌 知乎 编辑:程序博客网 时间:2024/05/17 06:45
题目链接:Ice Walls
题目大意:给出平面上一些与坐标轴平行且严格不相交的线段,穿过线段额外花费
题目分析:横竖线段分别考虑,先考虑竖线。枚举顶点,求出点和线段到顶点的
#include <bits/stdc++.h>using namespace std ;typedef long long LL ;typedef pair < double , int > pii ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 1005 ;const double eps = 1e-8 ;const double pi = acos ( -1.0 ) ;struct Point { int x , y ; Point () {} Point ( int x , int y ) : x ( x ) , y ( y ) {} Point operator - ( const Point& a ) const { return Point ( x - a.x , y - a.y ) ; } Point operator + ( const Point& a ) const { return Point ( x + a.x , y + a.y ) ; } void input () { scanf ( "%d%d" , &x , &y ) ; } double angle () { return atan2 ( y , x ) ; } double dis () { return sqrt ( 1.0 * x * x + 1.0 * y * y ) ; }} ;struct Line { int u , v ;} ;struct Node { int dis , idx ; bool operator < ( const Node& a ) const { return dis < a.dis ; }} ;Point p[MAXN] ;Line seg[MAXN] ;vector < pii > G ;Node a[MAXN << 1] ;int n , m , K , s , t ;int c[MAXN] ;double dis[MAXN][MAXN] ;double d[MAXN] ;int vis[MAXN] ;int rnk[MAXN] ;void add ( int x , int n , int v ) { for ( int i = x ; i ; i -= i & -i ) { c[i] += v ; }}int sum ( int x , int n ) { int ans = 0 ; for ( int i = x ; i <= n ; i += i & -i ) { ans += c[i] ; } return ans ;}int lfind ( double x , int l = 0 , int r = G.size () - 1 ) { while ( l < r ) { int m = l + r >> 1 ; if ( x + eps < G[m].first ) r = m ; else l = m + 1 ; } if ( x + eps > G[l].first ) ++ l ; return l + 1 ;}int rfind ( double x , int l = 0 , int r = G.size () - 1 ) { while ( l < r ) { int m = l + r + 1 >> 1 ; if ( G[m].first + eps < x ) l = m ; else r = m - 1 ; } if ( G[l].first + eps > x ) -- l ; return l + 1 ;}void deal ( int o , int cnt ) { int num = G.size () ; sort ( G.begin () , G.end () ) ; sort ( a , a + cnt ) ; for ( int i = 1 ; i <= num ; ++ i ) { rnk[G[i - 1].second] = i ; c[i] = 0 ; } for ( int i = 0 ; i < cnt ; ++ i ) { int idx = a[i].idx ; if ( idx < 0 ) { int u = seg[-idx].u ; int v = seg[-idx].v ; double angl = ( p[u] - p[o] ).angle () ; double angr = ( p[v] - p[o] ).angle () ; if ( angl > angr ) swap ( angl , angr ) ; int l = lfind ( angl ) ; int r = rfind ( angr ) ; add ( r , num , 1 ) ; add ( l - 1 , num , -1 ) ; } else { LL t = 1LL * K * sum ( rnk[idx] , num ) ; dis[o][idx] += t ; dis[idx][o] += t ; } }}void dij ( int s ) { for ( int i = 1 ; i <= m ; ++ i ) { d[i] = dis[s][i] ; vis[i] = 0 ; } d[s] = 0 ; vis[s] = 1 ; for ( int i = 1 ; i < m ; ++ i ) { double minv = 1e60 ; int u = s ; for ( int j = 1 ; j <= m ; ++ j ) { if ( !vis[j] && d[j] < minv ) { u = j ; minv = d[j] ; } } vis[u] = 1 ; for ( int j = 1 ; j <= m ; ++ j ) { if ( !vis[j] && d[u] + dis[u][j] < d[j] ) { d[j] = d[u] + dis[u][j] ; } } }}void solve () { m = 0 ; scanf ( "%d%d" , &n , &K ) ; for ( int i = 1 ; i <= n ; ++ i ) { p[++ m].input () ; seg[i].u = m ; p[++ m].input () ; seg[i].v = m ; } p[++ m].input () ; s = m ; p[++ m].input () ; t = m ; for ( int i = 1 ; i <= m ; ++ i ) { for ( int j = i + 1 ; j <= m ; ++ j ) { dis[i][j] = dis[j][i] = ( p[i] - p[j] ).dis () ; } } for ( int i = 1 ; i <= m ; ++ i ) { int cnt = 0 ; G.clear () ; for ( int j = 1 ; j <= m ; ++ j ) if ( j != i ) { if ( p[j].x > p[i].x ) { G.push_back ( pii ( ( p[j] - p[i] ).angle () , j ) ) ; a[cnt].dis = p[j].x - p[i].x ; a[cnt ++].idx = j ; } } for ( int j = 1 ; j <= n ; ++ j ) { int x = p[seg[j].u].x ; if ( x == p[seg[j].v].x && x > p[i].x ) { a[cnt].dis = x - p[i].x ; a[cnt ++].idx = -j ; } } deal ( i , cnt ) ; cnt = 0 ; G.clear () ; for ( int j = 1 ; j <= m ; ++ j ) if ( j != i ) { if ( p[j].y > p[i].y ) { G.push_back ( pii ( ( p[j] - p[i] ).angle () , j ) ) ; a[cnt].dis = p[j].y - p[i].y ; a[cnt ++].idx = j ; } } for ( int j = 1 ; j <= n ; ++ j ) { int y = p[seg[j].u].y ; if ( y == p[seg[j].v].y && y > p[i].y ) { a[cnt].dis = y - p[i].y ; a[cnt ++].idx = -j ; } } deal ( i , cnt ) ; } dij ( s ) ; printf ( "%.10f\n" , d[t] ) ;}int main () { int T ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { solve () ; } return 0 ;}
压缩后代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;typedef pair<double,int>pii;#define clr(a,x) memset(a,x,sizeof a)const int MAXN=1005;const double eps=1e-8;const double pi=acos(-1.0);struct Point{ int x,y; Point(){} Point(int x,int y):x(x),y(y){} Point operator - (const Point &a)const{return Point (x-a.x,y-a.y);} Point operator + (const Point &a)const{return Point (x+a.x,y+a.y);} void input(){scanf("%d%d",&x,&y);} double angle(){return atan2(y,x);} double dis(){return sqrt(1.0*x*x+1.0*y*y);}}p[MAXN];struct Line{ int u,v;}seg[MAXN];struct Node{ int dis,idx; Node(){} Node(int d,int i):dis(d),idx(i){} bool operator < (const Node&a)const{return dis<a.dis;}}a[MAXN<<1];pii G[MAXN];int n,m,K,s,t,c[MAXN],vis[MAXN],rnk[MAXN],num;double dis[MAXN][MAXN],d[MAXN];void add(int x,int n,int v){ for(int i=x;i;i-=i&-i)c[i]+=v;}int sum(int x,int n,int ans=0){ for(int i=x;i<=n;i+=i&-i)ans+=c[i]; return ans;}int lfind(double x,int l=0,int r=num-1){ for(int m=l+r>>1;l<r;m=l+r>>1)x+eps<G[m].first?r=m:l=m+1; if(x+eps>G[l].first)++l; return l+1;}int rfind(double x,int l=0,int r=num-1){ for(int m=l+r+1>>1;l<r;m=l+r+1>>1)G[m].first+eps<x?l=m:r=m-1; if(G[l].first+eps>x)--l; return l+1;}void deal(int o,int cnt){ int i,idx; sort(G,G+num); sort(a,a+cnt); for(i=1;i<=num;++i)rnk[G[i-1].second]=i,c[i]=0; for(i=0,idx=a[i].idx;i<cnt;++i,idx=a[i].idx){ if(idx<0){ int u=seg[-idx].u,v=seg[-idx].v; double angl=(p[u]-p[o]).angle(); double angr=(p[v]-p[o]).angle(); if(angl>angr)swap(angl,angr); int l=lfind(angl),r=rfind(angr); add(r,num,1); add(l-1,num,-1); }else{ LL t=1LL*K*sum(rnk[idx],num); dis[o][idx]+=t; dis[idx][o]+=t; } }}void dij(int s){ int i,j,u; for(i=1;i<=m;++i)d[i]=dis[s][i],vis[i]=0; for(d[s]=0,vis[s]=1,i=1,j,u;i<m;++i){ double minv=1e60; for(u=s,j=1;j<=m;++j)if(!vis[j]&&d[j]<minv)minv=d[u=j]; for(vis[u]=1,j=1;j<=m;++j)if(!vis[j]&&d[u]+dis[u][j]<d[j])d[j]=d[u]+dis[u][j]; }}void solve(){ m=0; scanf("%d%d",&n,&K); for(int i=1;i<=n;++i)p[seg[i].u=++m].input(),p[seg[i].v=++m].input(); p[s=++m].input(),p[t=++m].input(); for(int i=1;i<=m;++i)for(int j=i+1;j<=m;++j)dis[i][j]=dis[j][i]=(p[i]-p[j]).dis(); for(int i=1,j,cnt;i<=m;++i){ for(num=0,cnt=0,j=1;j<=m;++j)if(j!=i&&p[j].x>p[i].x){ G[num++]=pii((p[j]-p[i]).angle(),j); a[cnt++]=Node(p[j].x-p[i].x,j); } for(j=1;j<=n;++j){ int x=p[seg[j].u].x; if(x==p[seg[j].v].x&&x>p[i].x)a[cnt++]=Node(x-p[i].x,-j); } deal(i,cnt); for(num=0,cnt=0,j=1;j<=m;++j)if(j!=i&&p[j].y>p[i].y){ G[num++]=pii((p[j]-p[i]).angle(),j); a[cnt++]=Node(p[j].y-p[i].y,j); } for(j=1;j<=n;++j){ int y=p[seg[j].u].y; if(y==p[seg[j].v].y&&y>p[i].y)a[cnt++]=Node(y-p[i].y,-j); } deal(i,cnt); } dij(s); printf("%.10f\n",d[t]);}int main(){ int T; scanf("%d",&T); for(int i=1;i<=T;++i)solve(); return 0;}
0 0
- 【HDU】5817 Ice Walls【极角排序+树状数组+最短路】
- HDU Always Cook Mushroom (极角排序+树状数组)
- hdu 5032 树状数组+极角排序
- hdu 2145(最短路+排序)
- 【HDU】5549 Walk Around The Campsite【极角排序+set+最短路dp】
- HDU上的专题训练(背包问题-线段树+树状数组+DP优化+网络流+字符匹配+最短路+矩阵
- hdu 2145(最短路+排序)
- [DP] [1D1D优化] [树状数组] [最短路] 遭遇战 (clean)
- [HDU 5032 Always Cook Mushroom] 离线+极角排序+树状数组
- HDU 5032 Always Cook Mushroom(极角排序, 树状数组)
- HDU 5032 Always Cook Mushroom (极角排序 x 树状数组)
- hdu 1541 Stars(排序+树状数组)
- POJ 1161 Walls(floyd最短路)#by zh
- SGU 311. Ice-cream Tycoon 树状数组
- HDU上的专题训练(背包问题-线段树+树状数组+DP优化+网络流+字符匹配+最短路+矩阵乘法+搜索专题++)
- HDU 4109 拓扑排序(最短路思想)关键路径
- Hdu--1556--Color the ball(树状数组最简单运用)
- 最短路 2544hdu
- 仿淘宝物流效果(物流时间轴效果)
- org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
- nginx 无法解析php,(110: Connection timed out)
- 从零开始学JDBC--1.6 DQL--ResultSet的遍历方法
- Java高并发解决方案
- 【HDU】5817 Ice Walls【极角排序+树状数组+最短路】
- X服务器之xrandr
- 最近学习C语言
- Android:RxJava分析
- src与href属性的区别
- js 关于验证码cookie
- 第一行代码
- C++中获取系统时间(us)
- 文本框显示数据与保存数据