思路:直接建图,走一遍迪杰斯特拉,最后比较一下能到达边界点的最短路径就可以了。正确性还没具体验证,不过样例过了。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#define inf 0x3f3f3f3f
#define debug cout<<"debug"<<endl
using namespace std;
const int maxn=1e4+50;
vector<int> g[maxn];
vector<int> ok_node;
int n,d,diss[maxn],p[maxn],ans,ans_node;
bool vis[maxn];
struct Node{
int x,y;
Node(int xx,int yy):x(xx),y(yy){
}
Node(){
}
}node[maxn];
struct HeapNode{
int d,u;
bool operator < (const HeapNode& rhs) const{
return d>rhs.d;
}
};
struct Edge{
int from,to,dis;
Edge(int ff,int tt,int dd):from(ff),to(tt),dis(dd){
}
};
vector<Edge> edge;
double ok_dis(Node a,Node b){///计算距离
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool ok_bound(Node a){///确定边界范围内的点
if((a.x>=0&&a.x<=d&&a.y>=0&&a.y<=100)||(a.x>=d&&a.x<=100&&a.y>=100-d&&a.y<=100)||(a.x>=100-d&&a.x<=100&&a.y>=0&&a.y<=100-d)||(a.x>=d&&a.x<=100-d&&a.y>=0&&a.y<=d))
return true;
return false;
}
void dij(){
priority_queue<HeapNode> q;
memset(diss,inf,sizeof(diss));
diss[0]=0;
memset(vis,0,sizeof(vis));
q.push(HeapNode{0,0});
while(!q.empty()){
HeapNode temp=q.top();q.pop();
int uu=temp.u;
if(vis[uu]) continue;
vis[uu]=true;
for(int i=0;i<g[uu].size();i++){
Edge &e=edge[g[uu][i]];
if(diss[e.to]>diss[uu]+e.dis){
diss[e.to]=diss[uu]+e.dis;
p[e.to]=uu;
q.push(HeapNode{diss[e.to],e.to});
}
}
}
}
int main(){
while(scanf("%d",&n)!=EOF){
if(n==-1) break;
ans=inf;
memset(node,0,sizeof(node));
edge.clear(),memset(g,0,sizeof(g)),ok_node.clear();
scanf("%d",&d);
node[0].x=50,node[0].y=50;
if(ok_bound(node[0])) ok_node.push_back(0);///ok_node存放可以到达边界的点
for(int i=1;i<=n;i++){
int xx,yy;
scanf("%d%d",&xx,&yy);
node[i].x=xx+50,node[i].y=yy+50;
if(ok_bound(node[i])){
ok_node.push_back(i);
}
}
if(ok_node.empty()){
printf("-1\n");continue;
}
for(int i=0;i<=n;i++)
for(int j=i+1;j<=n;j++){
double dis=ok_dis(node[i],node[j]);
if(!i) dis-=7.5;
if(dis<=d){
edge.push_back(Edge(i,j,1));
g[i].push_back(edge.size()-1);///边编号从0开始
edge.push_back(Edge(j,i,1));
g[j].push_back(edge.size()-1);
}
}
if(edge.empty()){
printf("-1\n");continue;
}
dij();
for(int i=0;i<ok_node.size();i++){
int kk=ok_node[i];
if(diss[kk]<ans) ans=diss[kk],ans_node=kk;
}
stack<int> s;
int ee=ans_node;
for(;;){
if(!diss[ee]) break;
s.push(ee);
ee=p[ee];
}
printf("%d\n",ans+1);///最后别忘了还要跳到边界上
while(!s.empty()){
int temp=s.top();s.pop();
printf("%d %d\n",node[temp].x-50,node[temp].y-50);
}
}
return 0;
}