luogu P4162 [SCOI2009]最长距离

传送门

可以枚举两个点然后计算答案,至于是否合法,就要看可不可以通过移不超过\(t\)个箱子使得两点连通,也可以看做找一条路径使得路径上的1个数不超过\(t\)

所以可以考虑最短路,相邻的点两两连边,如果边的末端是1,那么边权为1,否则为0,再对每个点求单源最短路,注意初始距离为点上的数字(0/1)

最后就看两个点跑出来的距离是否\(\leq t\)救星了

神tm洛谷上不开o2跑得飞慢,比bzoj还慢qwq

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double
#define eps (1e-5)

using namespace std;
const int N=35,M=900+10;
il LL rd()
{
    re LL x=0,w=1;re char ch;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int to[M<<2],nt[M<<2],w[M<<2],hd[M],tot=1;
il void add(int x,int y,int z){++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;}
struct node
{
  int x,d;
  bool operator < (const node &bb) const {return d>bb.d;}
};
int n,m,kk,id[N][N],a[N][N],di[M][M];
db ans;

int main()
{
  n=rd(),m=rd(),kk=rd();
  char cc[N];
  for(int i=1;i<=n;i++)
    {
      scanf("%s",cc+1);
      for(int j=1;j<=m;j++)
        id[i][j]=(i-1)*m+j,a[i][j]=cc[j]-'0';
    }
  for(int i=1;i<=n;i++)
    {
      for(int j=1;j<=m;j++)
        {
          if(i>1) add(id[i-1][j],id[i][j],a[i][j]);
          if(i<n) add(id[i+1][j],id[i][j],a[i][j]);
          if(j>1) add(id[i][j-1],id[i][j],a[i][j]);
          if(j<m) add(id[i][j+1],id[i][j],a[i][j]);
        }
    }
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      {
        int ss=id[i][j];
        memset(di[ss],63,sizeof(di[ss]));
        di[ss][ss]=a[i][j];
        priority_queue<node> q;
        q.push((node){ss,a[i][j]});
        while(!q.empty())
          {
            int x=q.top().x,d=q.top().d;
            q.pop();
            if(d>di[ss][x]) continue;
            for(int i=hd[x];i;i=nt[i])
              {
                int y=to[i];
                if(di[ss][y]>di[ss][x]+w[i])
                  {
                    di[ss][y]=di[ss][x]+w[i];
                    q.push((node){y,di[ss][y]});
                  }
              }
          }
      }
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      for(int k=1;k<=n;k++)
        for(int l=1;l<=m;l++)
          if(di[id[i][j]][id[k][l]]<=kk) ans=max(ans,(db)(i-k)*(db)(i-k)+(db)(j-l)*(db)(j-l));
  printf("%.6lf\n",sqrt(ans));
  return 0;
}


posted @ 2018-10-10 22:07  ✡smy✡  阅读(91)  评论(0编辑  收藏  举报