BZOJ 1295: [SCOI2009]最长距离
题目大意:
给定一张网格图,求图上删掉T个障碍物之后能联通的两点的最大欧几里德距离是多少。
题解:
预处理两点间路径经过的最小障碍物数,判断是否小于T,更新答案。
代码:
#include<cstdio> #include<algorithm> #include<queue> #include<cmath> #define mp make_pair #define pr pair<int,int> #define sc second using namespace std; int n,m,T,cnt,dis[905],vis[905],f[905][905],a[35][35],last[905]; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; char s[35]; struct node{ int to,next,val; }e[10005]; priority_queue<pr,vector<pr>,greater<pr> > q; int calc(int x,int y){ return (x-1)*m+y; } void Dijkstra(int st){ for (int i=1; i<=n*m; i++) dis[i]=1e9,vis[i]=0; dis[st]=0; q.push(mp(0,st)); while (!q.empty()){ int x=q.top().sc; q.pop(); if (vis[x]) continue; vis[x]=1; for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (dis[V]>dis[x]+e[i].val){ dis[V]=dis[x]+e[i].val; q.push(mp(dis[V],V)); } } } for (int i=1; i<=n*m; i++) f[st][i]=dis[i]; } void add(int a,int b,int c){ e[++cnt].to=b; e[cnt].next=last[a]; e[cnt].val=c; last[a]=cnt; } int main(){ scanf("%d%d%d",&n,&m,&T); for (int i=1; i<=n; i++){ scanf("%s",s+1); for (int j=1; j<=m; j++) if (s[j]=='1') a[i][j]=1; } for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) for (int k=0; k<4; k++){ int fx=i+dx[k],fy=j+dy[k]; if (fx<1 || fx>n || fy<1 || fy>m) continue; add(calc(i,j),calc(fx,fy),a[fx][fy]); } for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) Dijkstra(calc(i,j)); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (a[i][j]){ for (int k=1; k<=n*m; k++) f[calc(i,j)][k]++; } double maxx=0; for (int x1=1; x1<=n; x1++) for (int y1=1; y1<=m; y1++) for (int x2=1; x2<=n; x2++) for (int y2=1; y2<=m; y2++) if (f[calc(x1,y1)][calc(x2,y2)]<=T) maxx=max(maxx,sqrt((double)(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))); printf("%lf\n",maxx); return 0; }