【jzoj4893】【过河】【最短路】

来源:互联网 发布:蓝桥物流软件多少钱 编辑:程序博客网 时间:2024/06/17 04:14

题目大意

这里写图片描述

解题思路

删掉半径小费用大的盘,盘就变成半径费用单调。以第i个柱,j种盘为点,枚举另一个点,利用单调性找出最小相交的盘子连边,每个柱小盘子向大盘子连边,边权为差值,再跑最短路就可以了。

code

#include<cmath>#include<cstdio>#include<algorithm>#define LL long long#define min(x,y) ((x<y)?x:y)#define max(x,y) ((x>y)?x:y)#define num(x,y) ((x-1)*m+y)#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)using namespace std;int const maxn=250;int T,n,m,w,gra,x[maxn+10],y[maxn+10],r[maxn+10],c[maxn+10],inq[maxn*maxn+10],q1[maxn*maxn*10+10],begin[maxn*maxn+10],to[maxn*maxn*maxn+10],len[maxn*maxn*maxn+10],next[maxn*maxn*maxn+10];double dis[maxn+10][maxn+10];long long f[maxn*maxn+10],inf=1e18;void insert(int u,int v,int w){    to[++gra]=v;    len[gra]=w;    next[gra]=begin[u];    begin[u]=gra;}int main(){    //freopen("river.in","r",stdin);    //freopen("river.out","w",stdout);    freopen("d.in","r",stdin);    freopen("d.out","w",stdout);    scanf("%d",&T);    fo(cas,1,T){        scanf("%d%d%d",&n,&m,&w);int ok=1;        fo(i,1,n)scanf("%d%d",&x[i],&y[i]);        fo(i,1,n)fo(j,1,n)dis[i][j]=sqrt(1ll*(x[i]-x[j])*(x[i]-x[j])+1ll*(y[i]-y[j])*(y[i]-y[j]));        fo(i,1,m)scanf("%d%d",&r[i],&c[i]);        fo(i,1,m-1)            fo(j,i+1,m){                if((r[j]>r[i])||((r[j]==r[i])&&(c[j]<c[i]))){                    swap(r[j],r[i]);                    swap(c[j],c[i]);                }            }        int tmp=m,mi=c[1];        for(int i=2;i<=tmp;i++){            if(c[i]>=mi){                fo(j,i,tmp-1){                    r[j]=r[j+1];                    c[j]=c[j+1];                }                tmp--;            }else mi=min(mi,c[i]);        }        m=tmp;        fo(i,1,m-1)            fo(j,i+1,m){                if(r[j]<r[i]){                    swap(r[j],r[i]);                    swap(c[j],c[i]);                }            }        int he=0,ti=0;        fo(i,1,n)fo(j,1,m)f[num(i,j)]=inf,inq[num(i,j)]=0;        fo(i,1,n)fo(j,1,m)            if(y[i]-r[j]<=0){                inq[q1[++ti]=num(i,j)]=1;                f[num(i,j)]=min(f[num(i,j)],c[j]);            }        gra=0;fo(i,1,n*m)begin[i]=0;int l;        fo(i,1,n)fo(k,1,n)if(i!=k){            l=m;            fo(j,1,m){                while((l>1)&&(dis[i][k]-1e-10<=r[j]+r[l-1]))l--;                if(dis[i][k]-1e-10<=r[j]+r[l])insert(num(i,j),num(k,l),c[l]);            }        }        fo(i,1,n)fo(j,1,m-1)insert(num(i,j),num(i,j+1),c[j+1]-c[j]);        for(;he!=ti;){            he++;            for(int i=begin[q1[he]];i;i=next[i])                if(f[q1[he]]+len[i]<f[to[i]]){                    f[to[i]]=f[q1[he]]+len[i];                    if(!inq[to[i]])inq[q1[++ti]=to[i]]=1;                }            inq[q1[he]]=0;        }        long long ans=inf;        fo(i,1,n)fo(j,1,m)            if(y[i]+r[j]>=w)                ans=min(ans,f[num(i,j)]);        if(ans!=inf)printf("%lld\n",ans);        else printf("impossible\n");    }    return 0;}
0 0
原创粉丝点击