码迷,mamicode.com
首页 > 其他好文 > 详细

USACO 2016 December Contest Gold T3: Lasers and Mirrors

时间:2019-07-20 23:25:52      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:usaco   space   UNC   htm   排序   spfa   最新   定向   cdn   

题目大意

出于某种原因,农夫约翰的牛总是在举行激光表演。

对于他们的最新展会,奶牛已经购买了一个大功率的激光器 - 这么大,事实上,他们似乎不能轻易地从它交付的位置移动。他们想以某种方式将激光的光发送到FJ物业另一侧的谷仓。激光器和谷仓都可以被认为位于FJ农场的地图上的2D平面中的点上。牛计划指挥激光器,使得它发出水平或竖直(即,与x或y轴平行)的光束。他们会将这个光束从一些镜子反射回去,直接到谷仓。

在农场上有N个栅栏(1N100,000),位于不同的二维点(也不同于激光和谷仓),牛可以安装镜子。可以选择不在护栏柱上安装镜子,在这种情况下,激光器将简单地直接通过柱子的顶部而不改变方向。如果母牛确实在栅栏柱上安装了一个镜子,它们会像/或\对齐,使得它将在垂直方向上重定向光束,反之亦然。

请计算牛需要使用的镜子的最小可能数量,以便将激光重新导向谷仓。

 

题目分析

考虑装了镜子后会有什么效果。

若一束光打过来到一个护栏上,沿原方向出去花费为0,改变90°后出去花费为1。

 

所以考虑把一个点拆成四个点。(这里借用洛谷大佬 _Yunluo_的一张图)(点开后为他滴题解)

技术图片

 

这样,蓝色边权为0,橙色边权为1。

至此,我们完成了“装镜子”,这个操作。

 

然后我们把所有点分别按照横坐标,纵坐标排序,建边。跑一遍最短路就行。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=1e5+10;
 4 const int Inf=0x3f3f3f3f;
 5 struct Node{
 6     int x,y,id;
 7 }p[MAXN+10];
 8 struct Egde{
 9     int to,nxt,d;
10 }e[MAXN<<4];
11 int cnt,head[MAXN<<3];
12 inline void add_edge(int u,int v,int d){
13     e[++cnt].to=v;e[cnt].d=d;e[cnt].nxt=head[u];head[u]=cnt;
14 }
15 inline bool cmp1(Node a,Node b){
16     return a.x==b.x?a.y<b.y:a.x<b.x;
17 }
18 inline bool cmp2(Node a,Node b){
19     return a.y==b.y?a.x<b.x:a.y<b.y;
20 }
21 
22 int n,S,T,p_cnt;
23 int new_Node[MAXN][4];
24 int dis[MAXN*4+10];
25 bool vis[MAXN*4+10];
26 queue<int> q;
27 inline void SPFA(){
28     for(int i=1;i<=MAXN*4;++i)
29         dis[i]=Inf;
30     q.push(S);
31     vis[S]=1;
32     dis[S]=0;
33     while(!q.empty()){
34         int x=q.front();
35         q.pop();
36         vis[x]=false;
37         for(int i=head[x],y;i;i=e[i].nxt){
38             y=e[i].to;
39             if(dis[y]>dis[x]+e[i].d){
40                 dis[y]=dis[x]+e[i].d;
41                 if(!vis[y]){
42                     q.push(y);
43                     vis[y]=true;
44                 }
45             }
46         }
47     }
48 }
49 
50 int main(){
51     for(int i=1;i<=MAXN;++i) p[i].id=i;
52     scanf("%d%d%d%d%d",&n,&p[1].x,&p[1].y,&p[2].x,&p[2].y);
53     n+=2;
54     for(int i=3;i<=n;++i)
55         scanf("%d%d",&p[i].x,&p[i].y);
56     S=++p_cnt;T=++p_cnt;
57     for(int i=1;i<=n;++i)
58         for(int j=0;j<=3;++j)
59             new_Node[i][j]=++p_cnt;
60     for(int i=1;i<=n;++i){
61         add_edge(new_Node[i][0],new_Node[i][1],0);add_edge(new_Node[i][1],new_Node[i][0],0);
62         add_edge(new_Node[i][2],new_Node[i][3],0);add_edge(new_Node[i][3],new_Node[i][2],0);
63         
64         add_edge(new_Node[i][2],new_Node[i][0],1);add_edge(new_Node[i][0],new_Node[i][2],1);
65         add_edge(new_Node[i][2],new_Node[i][1],1);add_edge(new_Node[i][1],new_Node[i][2],1);
66         
67         add_edge(new_Node[i][3],new_Node[i][0],1);add_edge(new_Node[i][0],new_Node[i][3],1);
68         add_edge(new_Node[i][3],new_Node[i][1],1);add_edge(new_Node[i][1],new_Node[i][3],1);
69     }
70     sort(p+1,p+n+1,cmp1);
71     for(int i=2;i<=n;++i)
72         if(p[i].x==p[i-1].x){
73             add_edge(new_Node[p[i-1].id][3],new_Node[p[i].id][2],0);
74             add_edge(new_Node[p[i].id][2],new_Node[p[i-1].id][3],0); 
75         }
76     sort(p+1,p+n+1,cmp2);
77     for(int i=2;i<=n;++i)
78         if(p[i].y==p[i-1].y){
79             add_edge(new_Node[p[i-1].id][1],new_Node[p[i].id][0],0);
80             add_edge(new_Node[p[i].id][0],new_Node[p[i-1].id][1],0);
81         }
82     for(int i=0;i<=3;++i){
83         add_edge(S,new_Node[1][i],0);
84         add_edge(new_Node[2][i],T,0);
85     }    
86     //cout<<1<<endl;
87     SPFA();    
88     printf("%d\n",dis[T]>=Inf?-1:dis[T]);
89     return 0;
90 }

 

USACO 2016 December Contest Gold T3: Lasers and Mirrors

标签:usaco   space   UNC   htm   排序   spfa   最新   定向   cdn   

原文地址:https://www.cnblogs.com/LI-dox/p/11219516.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!