【BZOJ】【3007】拯救小云公主
思路题
我的naive的做法是二分答案+判定是否有路径可走……但是没有正确理解【走的方向任意】这句话……
其实就是说想咋走咋走= =360°无死角乱走……
所以其实是个平面上的问题……
我们可以换个方向来考虑……二分一个答案,判断英雄走到/走不到公主那里,是不是就等价于,boss控制的区域连起来了使得英雄走不到公主那里了?(狼抓兔子的即视感)
所以我们可以转化成从上边&左边,在boss之间走,使得走到下边&右边 路径上最大的一条边(边权代表着如果英雄从这两个boss之间经过,离两个boss最近的距离(所以就是$\frac{dis(boss[i],boss[j])}{2}$))最小。
这个好像不能SPFA?(明明是你蒻)……我WA40了……只能bellman-ford迭代了……
1 /************************************************************** 2 Problem: 3007 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:1176 ms 7 Memory:72104 kb 8 ****************************************************************/ 9 10 //Huce #3 A 11 #include<cmath> 12 #include<queue> 13 #include<vector> 14 #include<cstdio> 15 #include<cstdlib> 16 #include<cstring> 17 #include<iostream> 18 #include<algorithm> 19 #define rep(i,n) for(int i=0;i<n;++i) 20 #define F(i,j,n) for(int i=j;i<=n;++i) 21 #define D(i,j,n) for(int i=j;i>=n;--i) 22 using namespace std; 23 24 int getint(){ 25 int v=0,sign=1; char ch=getchar(); 26 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 27 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 28 return v*sign; 29 } 30 typedef long long LL; 31 const int N=3010,INF=~0u>>2; 32 const double eps=1e-5; 33 /*******************tamplate********************/ 34 struct Boss{ 35 int x,y; 36 Boss(){} 37 Boss(int x,int y):x(x),y(y){} 38 void read(){scanf("%d%d",&x,&y);} 39 }boss[N]; 40 double inf = 1 << 25,g[N][N],f[N]; 41 int n,row,line; 42 double dis(Boss a,Boss b){ 43 double x,y; 44 x=a.x-b.x; y=a.y-b.y; 45 return sqrt(x*x+y*y); 46 } 47 void build(){ 48 F(i,1,n+4) F(j,1,n+4) g[i][j]=inf; 49 F(i,1,n) F(j,i+1,n) 50 g[i][j]=g[j][i]=dis(boss[i],boss[j])/2; 51 F(i,1,n){ 52 g[n+1][i]=boss[i].y-1; 53 g[n+2][i]=row-boss[i].x; 54 g[i][n+3]=line-boss[i].y; 55 g[i][n+4]=boss[i].x-1; 56 } 57 } 58 59 bool vis[N]; 60 double solve(){ 61 memset(vis,0,sizeof vis); 62 F(i,1,n+4) f[i]=inf; 63 f[n+1]=f[n+2]=0; 64 vis[n+1]=vis[n+2]=1; 65 double mn; int l; 66 while(1){ 67 mn=inf; l=-1; 68 F(i,1,n+4) if (vis[i] && f[i]<mn){ 69 mn=f[i]; l=i; 70 } 71 if (l==-1) break; 72 F(i,1,n+4) 73 if (max(g[l][i],f[l])<f[i]){ 74 f[i]=max(g[l][i],f[l]); 75 vis[i]=1; 76 } 77 vis[l]=0; 78 } 79 return min(f[n+3],f[n+4]); 80 } 81 int main(){ 82 #ifndef ONLINE_JUDGE 83 freopen("input.txt","r",stdin); 84 // freopen("output.txt","w",stdout); 85 #endif 86 n=getint(); row=getint(); line=getint(); 87 F(i,1,n) boss[i].read(); 88 double ans=inf; 89 F(i,1,n){ 90 ans=min(ans,dis(Boss(1,1),boss[i])); 91 ans=min(ans,dis(Boss(row,line),boss[i])); 92 //用起始位置和结束位置更新答案 93 } 94 build(); 95 ans=min(ans,solve()); 96 printf("%.2lf\n",ans); 97 return 0; 98 }
UPD:果然是我spfa的姿势不对,终于A了,但是比迭代还要慢……我写的spfa就是shit QAQ
ZYF:因为是邻接矩阵(完全图),边都是满的……
1 /************************************************************** 2 Problem: 3007 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:2172 ms 7 Memory:72116 kb 8 ****************************************************************/ 9 10 //Huce #3 A 11 #include<cmath> 12 #include<queue> 13 #include<vector> 14 #include<cstdio> 15 #include<cstdlib> 16 #include<cstring> 17 #include<iostream> 18 #include<algorithm> 19 #define rep(i,n) for(int i=0;i<n;++i) 20 #define F(i,j,n) for(int i=j;i<=n;++i) 21 #define D(i,j,n) for(int i=j;i>=n;--i) 22 using namespace std; 23 24 int getint(){ 25 int v=0,sign=1; char ch=getchar(); 26 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 27 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 28 return v*sign; 29 } 30 typedef long long LL; 31 const int N=3010,INF=~0u>>2; 32 const double eps=1e-5; 33 /*******************tamplate********************/ 34 struct Boss{ 35 int x,y; 36 Boss(){} 37 Boss(int x,int y):x(x),y(y){} 38 void read(){scanf("%d%d",&x,&y);} 39 }boss[N]; 40 double inf = 1 << 25,g[N][N],f[N]; 41 int n,row,line; 42 double dis(Boss a,Boss b){ 43 double x,y; 44 x=a.x-b.x; y=a.y-b.y; 45 return sqrt(x*x+y*y); 46 } 47 void build(){ 48 F(i,1,n+4) F(j,1,n+4) g[i][j]=inf; 49 F(i,1,n) F(j,i+1,n) 50 g[i][j]=g[j][i]=dis(boss[i],boss[j])/2; 51 F(i,1,n){ 52 g[n+1][i]=boss[i].y-1; 53 g[n+2][i]=row-boss[i].x; 54 g[i][n+3]=line-boss[i].y; 55 g[i][n+4]=boss[i].x-1; 56 } 57 } 58 int Q[N]; 59 bool inq[N]; 60 double solve(){ 61 F(i,1,n+4) f[i]=INF; 62 f[n+1]=f[n+2]=0; 63 int l=0,r=0; 64 Q[r++]=n+1; inq[n+1]=1; 65 Q[r++]=n+2; inq[n+2]=1; 66 while(l!=r){ 67 int x=Q[l]; inq[x]=0; 68 l=(l+1)%N; 69 inq[x]=0; 70 F(i,1,n+4) 71 if (max(g[x][i],f[x])<f[i]){ 72 f[i]=max(g[x][i],f[x]); 73 if (!inq[i]){ 74 Q[r]=i; 75 r=(r+1)%N; 76 inq[i]=1; 77 } 78 } 79 } 80 return min(f[n+3],f[n+4]); 81 } 82 int main(){ 83 #ifndef ONLINE_JUDGE 84 freopen("input.txt","r",stdin); 85 // freopen("output.txt","w",stdout); 86 #endif 87 n=getint(); row=getint(); line=getint(); 88 F(i,1,n) boss[i].read(); 89 double ans=1e20; 90 F(i,1,n){ 91 ans=min(ans,dis(Boss(1,1),boss[i])); 92 ans=min(ans,dis(Boss(row,line),boss[i])); 93 //ÓÃÆðʼλÖúͽáÊøλÖøüд𰸠94 } 95 build(); 96 ans=min(ans,solve()); 97 printf("%.2lf\n",ans); 98 return 0; 99 }
3007: 拯救小云公主
Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 71 Solved: 36
[Submit][Status][Discuss]
Description
英雄又即将踏上拯救公主的道路……
这次的拯救目标是——爱和正义的小云公主。
英雄来到boss的洞穴门口,他一下子就懵了,因为面前不只是一只boss,而是上千只boss。当英雄意识到自己还是等级1的时候,他明白这就是一个不可能完成的任务。
但他不死心,他在想,能不能避开boss去拯救公主呢,嘻嘻。
Boss的洞穴可以看成一个矩形,英雄在左下角(1,1),公主在右上角(row,line)。英雄为了避开boss,当然是离boss距离越远越好了,所以英雄决定找一条路径使到距离boss的最短距离最远。
Ps:英雄走的方向是任意的。
你可以帮帮他吗?
当英雄找到了美丽漂亮的小云公主,立刻就被boss包围了!!!英雄缓闭双眼,举手轻挥,白光一闪后使用了回城卷轴,回到了城堡,但只有小云公主回去了……因为英雄忘了进入回城的法阵了。
Input
第一行,输入三个整数,n表示boss的数目,row,line表示矩形的大小;
接下来n行,每行分别两个整数表示boss的位置坐标。
Output
输出一个小数,表示英雄的路径离boss的最远距离,精确到小数点后两位。
Sample Input
1 3 3
2 2
输出样例1:
1.00
输入样例2:
1 3 3
3 1
输出样例2:
2.00
2 2
输出样例1:
1.00
输入样例2:
1 3 3
3 1
输出样例2:
2.00
Sample Output
HINT
100%数据,n<=3000;