1295: [SCOI2009]最长距离
思路
每次选两个点,spfa,到每个点需要搬多少石头,再枚举两个点,判断是否可以在搬得石头的个数小于t的情况下,走到,取最大值。
zz的我,spfa都不会写了。。。
代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 7 using namespace std; 8 9 const int N = 35; 10 const int INF = 1e9; 11 12 char s[N][N]; 13 int mp[N][N],dis[N][N],q[100100]; 14 bool vis[N][N]; 15 int dx[4] = {0,0,1,-1},dy[4] = {1,-1,0,0}; 16 int n,m,t,L,R; 17 18 #define getid(x,y) (x-1)*n+y 19 #define getx(z) (z-1)/n+1 20 #define gety(z) ((z%m)==0)?m:(z%m) 21 22 void bfs(int a,int b) { 23 for (int i=1; i<=n; ++i) 24 for (int j=1; j<=m; ++j) dis[i][j] = INF,vis[i][j] = false; 25 dis[a][b] = mp[a][b]; 26 vis[a][b] = true; 27 L = 1,R = 0; 28 q[++R] = getid(a,b); 29 while (L <= R) { 30 int x = getx(q[L]),y = gety(q[L]);L++;//潜在bug不可以gety(q[L++]); 31 for (int i=0; i<4; ++i) { 32 int xx = x + dx[i],yy = y + dy[i]; 33 if (xx < 1 || xx > n || yy > m || yy < 1) continue; 34 if (dis[xx][yy] <= dis[x][y] + mp[xx][yy]) continue; 35 dis[xx][yy] = dis[x][y] + mp[xx][yy]; 36 q[++R] = getid(xx,yy); 37 vis[xx][yy] = true; 38 } 39 vis[x][y] = false; 40 } 41 } 42 43 int main() { 44 cin >> n >> m >> t; 45 for (int i=1; i<=n; ++i) { 46 scanf("%s",s[i]+1); 47 } 48 for (int i=1; i<=n; ++i) 49 for (int j=1; j<=m; ++j) 50 mp[i][j] = s[i][j]=='1'; 51 double ans = 0; 52 for (int a=1; a<=n; ++a) { 53 for (int b=1; b<=m; ++b) { 54 bfs(a,b); 55 for (int c=1; c<=n; ++c) // 也是从1开始 56 for (int d=1; d<=m; ++d) // 57 if (mp[a][b] + dis[c][d] <= t) 58 ans = max(ans,sqrt(1.0*(a-c)*(a-c)+1.0*(b-d)*(b-d))); 59 } 60 } 61 printf("%.6lf",ans); 62 return 0; 63 }