luogu P4162 [SCOI2009]最長距離
阿新 • • 發佈:2018-10-11
its c++ char add long long sco pro 是否 pop
傳送門
可以枚舉兩個點然後計算答案,至於是否合法,就要看可不可以通過移不超過\(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; }
luogu P4162 [SCOI2009]最長距離