1. 程式人生 > >bzoj1295: [SCOI2009]最長距離

bzoj1295: [SCOI2009]最長距離

space math ret algo max ans can div 插頭dp

很有趣的題啊。

看到n、m、T這麽小,一開始還以為是插頭DP。。。

結果實際上就是暴力枚舉起點,然後往周圍spfa,d數組記錄經過的障礙數且不能超過T,跑完就判斷可以到達那些點,暴力枚舉,記錄最大值

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int dx[4]={-1,0,1,0
}; const int dy[4]={0,1,0,-1}; int n,m,T; int mp[110][110]; struct node { int x,y; }list[11000]; int d[110][110]; bool v[110][110]; double spfa(int stx,int sty) { if(mp[stx][sty]>T)return 0; memset(d,63,sizeof(d));d[stx][sty]=mp[stx][sty]; memset(v,false,sizeof(v));v[stx][sty]=true
; list[1].x=stx;list[1].y=sty; int head=1,tail=2; while(head!=tail) { int x=list[head].x,y=list[head].y; for(int i=0;i<=3;i++) { int tx=x+dx[i],ty=y+dy[i]; if(tx>0&&tx<=n&&ty>0&&ty<=m) {
if(d[tx][ty]>d[x][y]+mp[tx][ty]&&d[x][y]+mp[tx][ty]<=T) { d[tx][ty]=d[x][y]+mp[tx][ty]; if(v[tx][ty]==false) { v[tx][ty]=true; list[tail].x=tx;list[tail].y=ty; tail++;if(tail==10500)tail=1; } } } } v[x][y]=false; head++;if(head==10500)head=1; } double ret=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(d[i][j]<=T) ret=max( ret,sqrt(double(stx-i)*double(stx-i)+double(sty-j)*double(sty-j)) ); return ret; } char ss[110]; int main() { scanf("%d%d%d",&n,&m,&T); for(int i=1;i<=n;i++) { scanf("%s",ss+1); for(int j=1;j<=m;j++) mp[i][j]=ss[j]-0; } double ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { double d=spfa(i,j); ans=max(ans,d); } printf("%.6lf\n",ans); return 0; }

bzoj1295: [SCOI2009]最長距離