计蒜客 百度地图的实时路况
题目
中文题意
思路
如果枚举不走的点,那么会是n^4,会超时,在知道floyd的前提下,我们可以二分那个不走的点。就例如有1234四个点,我们先二分后一半得出经过34松弛的矩阵,然后再得出经过234优化的矩阵,这样不走1的结果就出来了,再回溯递归另一半134的矩阵,不走2的答案就出来了,再回溯得出12的矩阵,再递归124得出3,再回溯12,递归123,4的答案就出来了,实在不行可以看代码理解。(还能这么二分。。666)
代码
#include<cstdio>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=310;
int ma[10][maxn][maxn];
ll ans;
int n;
void solve(int L,int R,int dep)
{
if(L==R)
{
for(int i=1; i<=n; i++)
{
if(i==L) continue;
for(int j=1; j<=n; j++)
{
if(j==L) continue;
ans+=ma[dep][i][j];
}
}
return;
}
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
ma[dep+1][i][j]=ma[dep][i][j];
int m=L+R>>1;
for(int k=m+1; k<=R; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
if(i==j) continue;
if(ma[dep+1][i][k]==-1||ma[dep+1][k][j]==-1) continue;
if(ma[dep+1][i][j]==-1)
ma[dep+1][i][j]=ma[dep+1][i][k]+ma[dep+1][k][j];
else
ma[dep+1][i][j]=min(ma[dep+1][i][j],ma[dep+1][i][k]+ma[dep+1][k][j]);
}
solve(L,m,dep+1);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
ma[dep+1][i][j]=ma[dep][i][j];
for(int k=L; k<=m; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
if(i==j) continue;
if(ma[dep+1][i][k]==-1||ma[dep+1][k][j]==-1) continue;
if(ma[dep+1][i][j]==-1)
ma[dep+1][i][j]=ma[dep+1][i][k]+ma[dep+1][k][j];
else
ma[dep+1][i][j]=min(ma[dep+1][i][j],ma[dep+1][i][k]+ma[dep+1][k][j]);
}
solve(m+1,R,dep+1);
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&ma[0][i][j]);
ans=0;
solve(1,n,0);
printf("%lld\n",ans);
return 0;
}