@AkamemakA
2022-06-29T02:34:30.000000Z
字数 1828
阅读 237
题解 Atcoder
题目链接:点我
有N张蹦床,每张蹦床i在的位置有一个属性值;一个人本身有一个属性值。定义两蹦床之间的距离为:
4-10 0 10 0 510 0 111 0 1
2
当时,不存在一张蹦床,使得从此开始可以跳到所有蹦床。
当时,他可以从号蹦床开始,跳到所有蹦床。
例如,他跳到号蹦床可以用如下操作:
720 31 113 4 3-10 -15 234 26 5-2 39 40 -50 15 -20 2
18
这道题当然可以暴力解决。
从小到大枚举,对每一个,枚举每一个点,看从此点能否遍历到每一个点,时间复杂度。(亲测,还是能过几个点的(doge))
不过,这种暴力解法却给我们提供了一些思路。
那么如何去快速判断能否从某一个点到达其他所有点呢?
于是问题得到简化。对于每两个点,如果从能够到达,则这个图上从到有一条边。
用邻接矩阵存储这个图,最后直接用Floyd算法即可直接判断是否连通。
需要注意的是,能够从走到,并不意味着能够从走到,也就是说,这个图不是双向的。不能算出一向,就定了另一向。还有就是要注意数据范围,亲测不开会。
#include<bits/stdc++.h>using namespace std;const int N=205;#define int long long //超级懒狗int n;int x[N],y[N],p[N];int a[N][N]; //a[i][j]表示从i到j的距离bool b[N][N]; //邻接矩阵inline bool check(int mid){memset(b,0,sizeof b); //多次check,需要初始化for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i!=j)b[i][j]=(p[i]*mid>=a[i][j]); //若i能到j,则b[i][j]=1;否则为0。for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i!=j&&j!=k&&i!=k)b[i][j]|=b[i][k]&b[k][j]; //Floyd模板for(int i=1;i<=n;i++){bool g=1;for(int j=1;j<=n;j++)if(b[i][j]==0&&i!=j) g=0;if(g) return 1;} //枚举每个点,看从此点能否到达其他所有点,即是否b[i]中除第i个数以外的元素都为1return 0;}signed main() //signed超懒型{cin>>n;for(int i=1;i<=n;i++){scanf("%lld%lld%lld",&x[i],&y[i],&p[i]);for(int j=1;j<i;j++)a[i][j]=a[j][i]=abs(x[i]-x[j])+abs(y[i]-y[j]); //计算距离}int l=0,r=1e10,ans=0;while(l<=r){int mid=(l+r)/2;//long long间不能使用位运算if(check(mid)) r=mid-1,ans=mid;else l=mid+1;} //二分模板(注意l与r的取值)cout<<ans;return 0;}
完结撒花~