题解 [BZOJ1295][SCOI2009] 最长距离

题面

解析

\(n\)只有\(30\)可以直接枚举每个矩形,

判断他们的左上角到右下角或右上角到左上角的最短路是否小于\(T\).

最短路可以用\(dijkstra\).

一开始想用\(DP\)写最短路后来才知道思路有问题(因为最短路的方案可能不在矩形中).

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
using namespace std;

inline int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    return f*sum;
}

const int N=35;
struct edge{int to,next,w;}e[N*N*4];
int n,m,T,a[N][N];
int f[N*N][N*N],id[N][N],tot=0;
int ans=0,v[N*N];
int head[N*N],cnt=0;
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
priority_queue < pair<int,int> > que;

inline void add(int x,int y,int w){
    e[++cnt]=(edge){head[x],y,w};head[x]=cnt;
}

inline void dji(int s){
    memset(v,0,sizeof(v));
    que.push(make_pair(f[s][s],s));
    while(!que.empty()){
        int x=que.top().second;que.pop();
        if(v[x]) continue;v[x]=1;
        for(int i=head[x];i;i=e[i].to){
            int k=e[i].next;
            if(f[s][k]>f[s][x]+e[i].w){
                f[s][k]=f[s][x]+e[i].w;
                que.push(make_pair(-f[s][k],k));
            }
        }
    }
}

int main(){
    n=read();m=read();T=read();
    for(int i=1;i<=n;i++){
        char c[N];cin>>c;
        for(int j=0;j<m;j++) a[i][j+1]=c[j]-'0';
    }
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) id[i][j]=++tot;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=0;k<4;k++){
                int x=i+dx[k],y=j+dy[k];
                if(!x||x>n||!y||y>m) continue;
                add(id[i][j],id[x][y],a[x][y]);
            }
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) f[id[i][j]][id[i][j]]=a[i][j],dji(id[i][j]);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            for(int k=i;k<=n;k++){
                for(int l=j;l<=m;l++){
                    if(f[id[i][j]][id[k][l]]<=T||f[id[i][l]][id[k][j]]<=T) ans=max(ans,(k-i)*(k-i)+(l-j)*(l-j));
                }
            }
        }
    }
    double t=sqrt(ans);printf("%.6f\n",t);
    return 0;
}
上一篇:P4161 [SCOI2009]游戏 素数筛 + 背包DP


下一篇:P2657 [SCOI2009]windy数