Logo S08577 的博客

博客

8.5 mx放学路

...
S08577
2025-12-01 12:57:31

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-08-05 19:35:18

思路

Dij+二分。

一眼二分答案,二分最小能量值。

Dij是板子。注意两点之间的距离是最多能放传送锚点的个数,这里分讨,如果两点之间的距离不能和能量值整除,那么锚点个数为 $dis \div x$,否则为 $\max(0,dis \div x-1)$。

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<set>


using namespace std;

#define int long long
#define ll long long
#define Endl cout<<endl;
#define xy cout<<"xy";
#define yx cout<<"yx";
#define pii pair<int,int>
#define lowbit(x) x&(-x)

const int N=5e5+10;\/\/注意修改
const int mod=1e9+9;
const int Max=2e9+10;

struct node{
    int v,d;
    bool operator < (const node&b) const{
        return d>b.d;
    }
};

pii a[N];

int vis[N],ddis[N];



int n,m,x;

int dis(int u,int v,int k){
    int dis_d=abs(a[u].first-a[v].first)+abs(a[u].second-a[v].second);
    if(dis_d%k){
        return dis_d\/k;
    }
    else{
        return max(0ll,dis_d\/k-1);
    }
}

int Dij(int X){
    priority_queue<node> q;
    ddis[m+1]=0;
    q.push(node{m+1,0});
    while(!q.empty()){
        node t=q.top();
        q.pop();
        if(vis[t.v]) continue;
        vis[t.v]=1;
        for(int i=1;i<=m+2;i++){
            if(vis[i]) continue;
            int w=dis(t.v,i,X);
            if(ddis[i]>ddis[t.v]+w){
                ddis[i]=ddis[t.v]+w;
                if(!vis[i]){
                    q.push(node{i,ddis[i]});
                }
            }
        }
    }
    return ddis[m+2];
}

bool check(int X){
    for(int i=1;i<=m+2;i++) vis[i]=0;
    for(int i=1;i<=m+2;i++) ddis[i]=Max;
    return Dij(X)<=x;
}

signed main(){
    
\/\/    freopen("road.in","r",stdin);
\/\/    freopen("road.out","w",stdout);

    int sx,sy,ex,ey;
    cin>>n>>m>>x;
    cin>>sx>>sy>>ex>>ey;
    for(int i=1;i<=m;i++){
        cin>>a[i].first>>a[i].second;
    }
    a[m+1]={sx,sy};
    a[m+2]={ex,ey};
    int l=1,r=2e9,res=0;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid)){
            r=mid;

        }
        else l=mid+1;
    }
    cout<<l;
    return 0;
}


\/\/唐儿祭天,法力无边。

\/*


 *\/

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。