• 刷题总结——飞飞侠(bzoj2143 最短路)


    题目:

    Description

    飞飞国是一个传说中的国度,国家的居民叫做飞飞侠。飞飞国是一个N×M的矩形方阵,每个格子代表一个街区。然而飞飞国是没有交通工具的。飞飞侠完全靠地面的弹射装置来移动。每个街区都装有弹射装置。使用弹射装置是需要支付一定费用的。而且每个弹射装置都有自己的弹射能力。我们设第i行第j列的弹射装置有Aij的费用和Bij的弹射能力。并规定有相邻边的格子间距离是1。那么,任何飞飞侠都只需要在(i,j)支付Aij的费用就可以任意选择弹到距离不超过Bij的位置了。如下图 

     

    (从红色街区交费以后可以跳到周围的任意蓝色街区。) 现在的问题很简单。有三个飞飞侠,分别叫做X,Y,Z。现在它们决定聚在一起玩,于是想往其中一人的位置集合。告诉你3个飞飞侠的坐标,求往哪里集合大家需要花的费用总和最低。

    Input

    输入的第一行包含两个整数N和M,分别表示行数和列数。接下来是2个N×M的自然数矩阵,为Aij和Bij 最后一行六个数,分别代表X,Y,Z所在地的行号和列号。

    Output

    第一行输出一个字符X、Y或者Z。表示最优集合地点。第二行输出一个整数,表示最小费用。如果无法集合,只输出一行NO

    Sample Input

    4 4
    0 0 0 0
    1 2 2 0
    0 2 2 1
    0 0 0 0
    5 5 5 5
    5 5 5 5
    5 5 5 5
    5 5 5 5
    2 1 3 4 2 2

    Sample Output

    Z
    15
    【范围】
    100% 1 < = N, M < = 150; 0 < = Aij < = 10^9; 0 < = Bij < = 1000

    题解:

      这道题主要是建边方式很巧妙···如果直接建边跑迪杰斯特拉是爆空间的···

      我们根据每个点能够弹射的距离S将点拆成S+1个点,分别为g[x][y][0-S],xy为该点坐标··第三维为点的高度··其中高度大于等于1的点只能到达它的上、下、左、右、以及原地的低一层走,且边长为0···然后我们将高度为0的点g[x][y][0]根据弹射的距离S连向点g[x][y][S],边长为它的弹射费用··然后跑三次最短路即可

    代码:

      (ps:该代码在bzoj上超空间了··原因是我的单调队列偷懒没用结构体从而多开了几个占空间的数组···懒得改过来了··)

      

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=205;
    priority_queue< pair<long long,int> >que;
    const int Gox[6]={0,0,-1,1,0,0};
    const int Goy[6]={0,0,0,0,-1,1};
    long long dis[N][N][2*N];
    int anss[4][4],H,val[N][N],len[N][N],n,m,id[N][N][N*2],x[4],y[4],idx[N*N*N*2],idy[N*N*N*2],idh[N*N*N*2];
    inline int R(){
        char c;int f=0;
        for(c=getchar();c<'0'||c>'9';c=getchar());
        for(;c<='9'&&c>='0';c=getchar())    f=(f<<3)+(f<<1)+c-'0';
        return f;
    }
    inline void getans(int src,int des1,int des2){
        bool flag1=false,flag2=false;    
        while(!que.empty())    que.pop();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                for(int k=0;k<=H;k++)    dis[i][j][k]=2e+18;
        dis[x[src]][y[src]][0]=0;que.push(make_pair(0,id[x[src]][y[src]][0]));
        while(!que.empty()){
            int u=que.top().second;que.pop();
            if(u==id[x[des1]][y[des1]][0])  flag1=true;
            if(u==id[x[des2]][y[des2]][0])    flag2=true;
            if(flag1&&flag2)    break;
            if(idh[u]>=1){
                for(int i=1;i<=5;i++){
                    int tx=idx[u]+Gox[i],ty=idy[u]+Goy[i];
                    if(tx>=1&&tx<=n&&ty>=1&&ty<=m){
                        if(dis[tx][ty][idh[u]-1]>dis[idx[u]][idy[u]][idh[u]]){
                            dis[tx][ty][idh[u]-1]=dis[idx[u]][idy[u]][idh[u]];
                            que.push(make_pair(-dis[tx][ty][idh[u]-1],id[tx][ty][idh[u]-1]));
                        }
                    }
                }
            }
            else{
                int maxx=min(H,len[idx[u]][idy[u]]);
                if(dis[idx[u]][idy[u]][maxx]>dis[idx[u]][idy[u]][0]+val[idx[u]][idy[u]]){
                    dis[idx[u]][idy[u]][maxx]=dis[idx[u]][idy[u]][0]+val[idx[u]][idy[u]];
                    que.push(make_pair(-dis[idx[u]][idy[u]][maxx],id[idx[u]][idy[u]][maxx]));
                }
            }
        }
        anss[src][des1]=dis[x[des1]][y[des1]][0],anss[src][des2]=dis[x[des2]][y[des2]][0];
    }
    int main()
    {
        //freopen("friend.in","r",stdin);
        //freopen("friend.out","w",stdout);
        n=R(),m=R();H=max(n,m);int temp=0;H*=2;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                for(int k=0;k<=H;k++)    id[i][j][k]=++temp,idx[temp]=i,idy[temp]=j,idh[temp]=k;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)    len[i][j]=R();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)    val[i][j]=R();
        for(int i=1;i<=3;i++)    x[i]=R(),y[i]=R();
        getans(1,2,3),getans(2,1,3),getans(3,1,2);long long ans=2e+18;int pos;
        for(int i=1;i<=3;i++)    
        {    
            long long temp=0;
            for(int j=1;j<=3;j++){
                if(i==j)  continue;    
                temp+=anss[j][i];
            }
            if(temp<ans)    ans=temp,pos=i;
        }
        if(pos==1)    cout<<"X"<<"
    ";        
        else if(pos==2)  cout<<"Y"<<"
    ";
        else if(pos==3)  cout<<"Z"<<"
    ";
        cout<<ans<<"
    ";return 0;
    }

      

  • 相关阅读:
    iOS开发之集成iOS9中的Core Spotlight Framework搜索App的内容
    Masonry介绍与使用实践(快速上手Autolayout)(转)
    NSUserDefaults 简介,使用 NSUserDefaults 存储自定义对象(转)
    UIViewController 中的 willMoveToParentViewController和didMoveToParentViewController的使用(转载)
    iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译
    iOS在UITableView全面解析
    iOS UILabel详解(转载)
    UIScrollViewDelegate-委托方法API
    wordpress通过代码禁用IE8, IE9,IE10等IE浏览器兼容视图模式(Compatibility View)
    LNMP安装WordPress3.4.2看不到主题解决方法
  • 原文地址:https://www.cnblogs.com/AseanA/p/7763050.html
Copyright © 2020-2023  润新知