luogu4473 BZOJ2143 2011[国家集训队]飞飞侠

题目戳这里

有问题可以在博客@

应该还会有人来看吧,嘻嘻


正题:

题目大意:

题目很清楚,就是一个点有一定的范围,会有一定的花费
求三个点中的任意两个点到另一个点的最小花费
(麻麻教育我千万读好题目(>_<)~)

思路

很容易想到跑最短路,但是建边的话,根本存不下来

所以我们直接存点的坐标,然后直接遍历范围内每个点就好了(遍历是看图找规律吧,反正我动脑子看不出来)

跑一边最短路就好了

bzoj完全没问题,这里指luogu

spfa?他好像又死了(o2水过)

堆优化迪杰斯特拉是个好东西

我是先写的spfa,然后改了改一丢丢就写成了迪杰斯特拉,感觉他俩好像啊

下面是dijkstar和死了的spfa

代码:堆优化迪杰斯特拉

#include 
#include 
#include 
#include 
#include 
#include 
#define maxn 155
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
int a[maxn][maxn];
int b[maxn][maxn];
int dis[maxn][maxn];
int x[4],y[4];
int PKU[4][4];
struct node 
{
    int x,y,q;
    node(int xx,int yy,int qq)
    {
        x=xx;y=yy;
        q=qq;
    }
    bool operator < (const node &a) const 
    {
        return q>a.q;
    }
};
inline int read()
{
    int x=0,f=1;char s=getchar();
    while('0'>s||s>'9') {if(s=='-')f=-1;s=getchar();}
    while('0'<=s&&s<='9') {x=(x<<3)+(x<<1)+s-'0';s=getchar();}
    return x*f;
}
void dijstra(int js)
{
    memset(dis,inf,sizeof(dis));
    priority_queue q;
    q.push(node(x[js],y[js],0));
    dis[x[js]][y[js]]=0;
    while(!q.empty())
    {
        node u=q.top();
        q.pop();
        if(dis[u.x][u.y]!=u.q) continue;
        int len=b[u.x][u.y];
        int v=dis[u.x][u.y]+a[u.x][u.y];
        for(int i=max(1,u.x-len);i<=min(n,u.x+len);++i)
        {
            int tmp=len-abs(u.x-i);
            for(int j=max(1,u.y-tmp);j<=min(m,u.y+tmp);j++)
            {
                if(dis[i][j] > v)
                {
                    dis[i][j] = v;
                    q.push(node(i,j,dis[i][j]));
                }
            }
        }
    }
    for(int i=1;i<=3;++i) PKU[js][i]=dis[x[i]][y[i]];
}
int main(int argc, char const *argv[])
{
    n=read();m=read();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            b[i][j]=read();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            a[i][j]=read();
    for (int i = 1; i <= 3; ++i)
    {
        x[i]=read();
        y[i]=read();
    }
    for(int i=1;i<=3;++i) dijstra(i);
    int id=0,ans=inf;
    for(int i=1;i<=3;++i)
    {
        int tm=PKU[1][i]+PKU[2][i]+PKU[3][i];
        if(ans>tm) ans=tm,id=i;
    }
    if(ans==inf) return puts("NO"),0;
    if(id==1) puts("X");
    if(id==2) puts("Y");    
    if(id==3) puts("Z");
    printf("%d",ans);
    return 0;
}

代码:spfa

    #include 
#include 
#include 
#include 
#include 
#include 
#define maxn 155
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
int a[maxn][maxn];
int b[maxn][maxn];
int dis[maxn][maxn];
int vis[maxn][maxn];
int x[4],y[4];
int PKU[4][4];
struct node 
{
    int x,y;
    node(int xx,int yy)
    {
        x=xx;y=yy;
    }
};
inline int read()
{
    int x=0,f=1;char s=getchar();
    while('0'>s||s>'9') {if(s=='-')f=-1;s=getchar();}
    while('0'<=s&&s<='9') {x=(x<<3)+(x<<1)+s-'0';s=getchar();}
    return x*f;
}
void spfa(int js)
{
    memset(dis,inf,sizeof(dis));
    queue q;
    q.push(node(x[js],y[js]));
    dis[x[js]][y[js]]=0;
    while(!q.empty())
    {
        node u=q.front();
        q.pop();vis[u.x][u.y]=0;
        int len=b[u.x][u.y];
        int v=dis[u.x][u.y]+a[u.x][u.y];
        for(int i=max(1,u.x-len);i<=min(n,u.x+len);++i)
        {
            int tmp=len-abs(u.x-i);
            for(int j=max(1,u.y-tmp);j<=min(m,u.y+tmp);j++)
            {
                if(dis[i][j] > v)
                {
                    dis[i][j] = v;
                    if(!vis[i][j])
                    {
                        vis[i][j]=1;
                        q.push(node(i,j));
                    }
                }
            }
        }
    }
    for(int i=1;i<=3;++i) PKU[js][i]=dis[x[i]][y[i]];
}
int main(int argc, char const *argv[])
{
    n=read();m=read();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            b[i][j]=read();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            a[i][j]=read();
    for (int i = 1; i <= 3; ++i)
    {
        x[i]=read();
        y[i]=read();
    }
    for(int i=1;i<=3;++i) spfa(i);
    int id=0,ans=inf;
    for(int i=1;i<=3;++i)
    {
        int tm=PKU[1][i]+PKU[2][i]+PKU[3][i];
        if(ans>tm)
        {
            ans=tm;
            id=i;
        }
    }
    if(ans==inf)
        return puts("NO"),0;
    if(id==1)
        puts("X");
    if(id==2)
        puts("Y");    
    if(id==3)
        puts("Z");
    printf("%d",ans);
    return 0;
}

厚颜无耻的骗波赞( • ̀ω•́ )✧

你可能感兴趣的:(luogu4473 BZOJ2143 2011[国家集训队]飞飞侠)