【spfa】bzoj1295 [SCOI2009]最长距离

题意:给你一个n*m的点阵、有些点是障碍,求一个欧几里得距离最大的点对(A,B),使得在移走的障碍≤T的情况下,可以从A走到B。

建图,跑n*m次spfa,求出从 每个点 出发到 其他所有点 的 经过的障碍数。若这个值<=T,则可以用来更新答案。

 1 #include<cstdio>
 2 #include<queue>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
 8 queue<int>q;
 9 char map[31][31];
10 int n,en,m,K,first[50001],next[50001],v[50001],w[50001],dis[50001],num[31][31];
11 bool inq[50001];
12 double ans;
13 void init(const int &s)
14 {memset(dis,0x7f,sizeof(dis)); inq[s]=true; dis[s]=0; q.push(s);}
15 void AddEdge(const int &U,const int &V,const int &W)
16 {v[++en]=V; w[en]=W; next[en]=first[U]; first[U]=en;}
17 int sqr(const int &x){return x*x;}
18 double Euclid_Dis(const int &x1,const int &y1,const int &x2,const int &y2)
19 {return sqrt(sqr(x1-x2)+sqr(y1-y2));}
20 void spfa(const int &s)
21 {
22     init(s);
23     while(!q.empty())
24       {
25           int cur=q.front();
26           for(int i=first[cur];i;i=next[i])
27             if(dis[v[i]]>dis[cur]+w[i])
28               {
29                 dis[v[i]]=dis[cur]+w[i];
30                 if(!inq[v[i]])
31                   {
32                     q.push(v[i]);
33                     inq[v[i]]=true;
34                   }
35               }
36           q.pop(); inq[cur]=false;
37       }
38 }
39 void calc(const int &x,const int &y)
40 {
41     K-=(map[x][y]==‘1‘);
42     for(int i=0;i<n;i++)
43       for(int j=0;j<m;j++)
44         if(dis[num[i][j]]<=K)
45           ans=max(ans,Euclid_Dis(x,y,i,j));
46     K+=(map[x][y]==‘1‘);
47 }
48 void BuildGraph()
49 {
50     for(int i=0;i<n;i++)
51       for(int j=0;j<m;j++)
52         for(int k=0;k<4;k++)
53           {
54             int tx=i+dx[k],ty=j+dy[k];
55             if(tx>=0&&tx<n&&ty>=0&&ty<n)
56               if(map[tx][ty]==‘1‘) AddEdge(num[i][j],num[tx][ty],1);
57               else AddEdge(num[i][j],num[tx][ty],0);
58           }
59 }
60 int main()
61 {
62     scanf("%d%d%d",&n,&m,&K);
63     for(int i=0;i<n;i++)
64       scanf("%s",map[i]);
65     for(int i=0;i<n;i++)
66       for(int j=0;j<m;j++)
67         num[i][j]=++en;
68     en=0;
69     BuildGraph();
70     for(int i=0;i<n;i++)
71       for(int j=0;j<m;j++)
72         {
73           spfa(num[i][j]);
74           calc(i,j);
75         }
76     printf("%.6lf\n",ans);
77     return 0;
78 }
时间: 2024-12-18 04:50:02

【spfa】bzoj1295 [SCOI2009]最长距离的相关文章

BZOJ1295: [SCOI2009]最长距离

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1295 转成最短路. #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstdio> #include<cmath> #include<queue> #define rep(i,l,r) for (in

【BZOJ 1295】 [SCOI2009]最长距离

1295: [SCOI2009]最长距离 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 945  Solved: 492 [Submit][Status][Discuss] Description windy有一块矩形土地,被分为 N*M 块 1*1 的小格子. 有的格子含有障碍物. 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离. 如果从格子A不可以走到格子B,就没有距离. 如果格子X和格子Y有公共边,并且X和Y

1295: [SCOI2009]最长距离

1295: [SCOI2009]最长距离 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 960  Solved: 498[Submit][Status][Discuss] Description windy有一块矩形土地,被分为 N*M 块 1*1 的小格子. 有的格子含有障碍物. 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离. 如果从格子A不可以走到格子B,就没有距离. 如果格子X和格子Y有公共边,并且X和Y均不

[BZOJ 1295][SCOI2009]最长距离(SPFA+暴力)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1295 分析:很巧妙的一道spfa从搜索的角度是搜索在所有1中搜索删除哪T个1,对整个图询问,这样肯定TLE 不妨反过来想一想:对于两个点,弄出联通这两个点所需删除的最少的1,那么就知道这两个点是否可以作为题目要求的起点和终点,如果满足算一下结果和ans比较一下就可以. 所以算法就出来了: 枚举起点(S,T),用SPFA跑出图上的所有点到起点这条路径联通的最少删除的1,那么ans=max(di

bzoj1295:[SCOI2009]最长距离

题目描述 windy有一块矩形土地,被分为 N*M 块 1*1 的小格子. 有的格子含有障碍物. 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离. 如果从格子A不可以走到格子B,就没有距离. 如果格子X和格子Y有公共边,并且X和Y均不含有障碍物,就可以从X走到Y. 如果windy可以移走T块障碍物,求所有格子间的最大距离. 保证移走T块障碍物以后,至少有一个格子不含有障碍物. 输入 输入文件maxlength.in第一行包含三个整数,N M T. 接下来有N行,每行

BZOJ 1295 SCOI2009 最长距离 SPFA+暴力

题目大意:给定一个棋盘,一些格子上有障碍物,可以移除T个障碍物,求移除后所有能互相到达的点对中的最大欧几里得距离 m,n<=30,900个点,我们可以枚举起始点,跑一遍SPFA,求出所有经过不超过T个障碍物可达的点,统计ans即可 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 40 usi

bzoj 1295: [SCOI2009]最长距离

1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 using namespace std; 6 int n,m,T; 7 double ans=0; 8 bool mp[31][31],inq[31][31],vis[31][31]; 9 int dis[31][31]; 10 int dx[4]={1,-1,0,0}; 11 int dy[4]={

bzoj 1295: [SCOI2009]最长距离 暴力+bfs最短路

题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1295 题解: 对每个点暴力跑一遍bfs,看能够到达的最远位置,这里如果有障碍物则距离为1,如果没有障碍物,则距离为0,用bfs跑距离<=t的所有点并更新答案. 代码: #include<iostream> #include<cstring> #include<cstdio> #include<utility> #include<queu

[SCOI2009] 最长距离

题目描述 windy有一块矩形土地,被分为 NM 块 11 的小格子. 有的格子含有障碍物. 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离. 如果从格子A不可以走到格子B,就没有距离. 如果格子X和格子Y有公共边,并且X和Y均不含有障碍物,就可以从X走到Y. 如果windy可以移走T块障碍物,求所有格子间的最大距离. 保证移走T块障碍物以后,至少有一个格子不含有障碍物. 输入输出格式 输入格式: 第一行包含三个整数,N M T. 接下来有N行,每行一个长度为M的字