相邻格子连双向边,如果一个点有障碍,那进它的边权就是1,否则是0
这样的话,两点间的最短路+[起始点有障碍],就是从一个点走到另一个需要清除的障碍的个数
求出最短路后枚举这两个点就可以了
然而30*30还是太大跑不开floyd,只能写一个dijkstra
1 #include<bits/stdc++.h> 2 #define CLR(a,x) memset(a,x,sizeof(a)) 3 using namespace std; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 typedef pair<int,int> pa; 7 const int maxn=35,npm=905; 8 9 inline ll rd(){ 10 ll x=0;char c=getchar();int neg=1; 11 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 12 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 13 return x*neg; 14 } 15 16 int id[maxn][maxn]; 17 int dis[npm][npm]; 18 int N,M,T; 19 char can[npm][npm]; 20 priority_queue<pa,vector<pa>,greater<pa> > q; 21 bool flag[npm]; 22 23 inline void chkmin(int s,int x,int y){ 24 if(dis[s][x]>y) 25 dis[s][x]=y,q.push(make_pair(y,x)); 26 } 27 28 inline void getdis(int s){ 29 CLR(dis[s],127);CLR(flag,0); 30 dis[s][s]=0;q.push(make_pair(0,s)); 31 while(!q.empty()){ 32 int p=q.top().second;q.pop(); 33 // printf("~%d %d %d ",s,p,dis[s][p]); 34 if(flag[p]) continue;flag[p]=1; 35 int i=(p-1)/M+1,j=p%M;if(!j) j=M; 36 if(i<N) chkmin(s,id[i+1][j],dis[s][p]+can[i+1][j]-'0'); 37 if(i>1) chkmin(s,id[i-1][j],dis[s][p]+can[i-1][j]-'0'); 38 if(j<M) chkmin(s,id[i][j+1],dis[s][p]+can[i][j+1]-'0'); 39 if(j>1) chkmin(s,id[i][j-1],dis[s][p]+can[i][j-1]-'0'); 40 } 41 } 42 43 int main(){ 44 //freopen("","r",stdin); 45 int i,j,k=0; 46 N=rd(),M=rd(),T=rd(); 47 for(i=1;i<=N;i++){ 48 scanf("%s",can[i]+1); 49 for(j=1;j<=M;j++) 50 id[i][j]=++k; 51 } 52 for(i=1;i<=N;i++){ 53 for(j=1;j<=M;j++){ 54 getdis(id[i][j]); 55 } 56 } 57 double ans=0; 58 for(i=1;i<=N;i++){ 59 for(j=1;j<=M;j++){ 60 for(k=1;k<=N;k++){ 61 for(int l=1;l<=M;l++){ 62 if(dis[id[i][j]][id[k][l]]+can[i][j]-'0'<=T) ans=max(ans,sqrt(0.0+(k-i)*(k-i)+(l-j)*(l-j))); 63 } 64 } 65 } 66 } 67 printf("%.6lf ",ans); 68 return 0; 69 }