bzoj1295: [SCOI2009]最长距离
很有趣的题啊。
看到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; }
pain and happy in the cruel world.