C题.[Codeforces 242C] King’s Path
题目链接
思路:
题目中这句话很关键所有线段的总长不超过105,也就是说,二维平面里最多只有105个允许走的点。所以可以把线段拆成点,用二维map标记,把每个点向八个方向连边,建图跑最短路。
//AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+7;
const int M=5e5+7;
struct Graph{
LL Inf=0x3f3f3f3f;
struct Edge{int v,Next;LL w;}e[M*2];
int n,m,vis[N],head[N],tot,path[N];//path记录路径
LL dis[N];
struct node{
int v;LL d;
bool operator <(const node &o)const{
return d>o.d;
}
};//优先队列类型
priority_queue<node>q;
void clear(){
while(!q.empty())q.pop();
memset(head,0,sizeof(head));
memset(path,0,sizeof(path));
tot=0;
}
void add(int u,int v,LL w){e[++tot]=(Edge){v,head[u],w};head[u]=tot;}
void addedge(int u,int v,LL w){add(u,v,w);add(v,u,w);}
void Dijkstra(int s){//+优先队列
for(int i=1;i<=n;i++)dis[i]=(i==s?0:Inf);//初始化
q.push(node{s,0});
while(!q.empty()){
node now=q.top();q.pop();
if(vis[now.v])continue;
vis[now.v]=1;
for(int j=head[now.v];j;j=e[j].Next)
if(dis[e[j].v]>dis[now.v]+e[j].w){
dis[e[j].v]=dis[now.v]+e[j].w;
q.push(node{e[j].v,dis[e[j].v]});
//path[e[j].v]=now.v; //记录路径
}
}
}
void print_path(int x){//打印最段路径, 调用时参数为终点
if(path[x]==0){
printf("%d ",x);
return;
}
print_path(path[x]);
printf("%d ",x);
}
}G;
map<int,map<int,int> >mp;
int n,cnt,x0,y0,x1,y1,p[N][2];
const int x_[8]={1,1,1,-1,-1,-1,0,0};
const int y_[8]={1,-1,0,1,-1,0,1,-1};
int main(){
cin>>x0>>y0>>x1>>y1;
cin>>n;
for(int i=1,r,a,b;i<=n;i++){//记录
scanf("%d%d%d",&r,&a,&b);
for(int j=a;j<=b;j++)
if(!mp[r][j]){
mp[r][j]=++cnt;
p[cnt][0]=r;
p[cnt][1]=j;
}
}
G.n=cnt;
for(int i=1;i<=cnt;i++){//建图
for(int j=0;j<8;j++){
int x=p[i][0]+x_[j],y=p[i][1]+y_[j];
if(x<1||y<1||x>1e9||y>1e9)continue;
if(mp[x].count(y))G.add(i,mp[x][y],1);
}
}
G.Dijkstra(mp[x0][y0]);//最短路
if(G.dis[mp[x1][y1]]==G.Inf)printf("-1");
else printf("%lld",G.dis[mp[x1][y1]]);
}