博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

题解 [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;
}

posted @ 2019-08-26 21:45  Hastin  阅读(100)  评论(0编辑  收藏  举报