HDU 5636 Shortest Path 分治+搜索剪枝

题意:bc round 74

分析(官方题解):

你可以选择分类讨论, 但是估计可能会写漏一些地方.

只要抽出新增边的端点作为关键点, 建立一个新图, 然后跑一遍floyd就好了. 复杂度大概O(6^2m)

注:然后我不会这种,这种floyd我觉得复杂度应该是复杂度应该是O(8^3m)

大概在千万级别,其实应该可以过,然后,其实只需要求单元最短路就行,然后是不是可以dij,然后就快一点

反正我也没写

我在比赛的时候写的是分治,考虑走不走新加的边每次走几条,以及走的顺序就好

然后全排列,时间复杂度是O(3^4m)的,大概在800w,然后由于这是单组样例800w*T

然后就超时了,然后比完赛,我就加了个剪枝,当前长度大于答案的时候,就返回

然后就1516ms过了,所以,以后记住要剪枝,不要图省事

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
typedef long long LL;
const int N=1e9+7;
int o[3],x[3],y[3],n,m,s,t,ans,T;
void dfs(int pos,int now,int sum)
{
    if(sum>=ans)return;
    ans=min(ans,abs(t-now)+sum);
    int i=o[pos];
    if(pos==3)
    {
        ans=min(ans,abs(t-now)+sum);
        return;
    }
    int tmp=sum+abs(now-x[i])+1;
    dfs(pos+1,y[i],tmp);
    tmp=sum+abs(now-y[i])+1;
    dfs(pos+1,x[i],tmp);
    dfs(pos+1,now,sum);
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<3; ++i)
        {
            scanf("%d%d",&x[i],&y[i]);
            if(x[i]>y[i])swap(x[i],y[i]);
        }
        LL res=0;
        for(int i=1; i<=m; ++i)
        {
            scanf("%d%d",&s,&t);
            ans=0x3f3f3f3f;
            o[0]=0,o[1]=1,o[2]=2;
            dfs(0,s,0);
            o[0]=0,o[1]=2,o[2]=1;
            dfs(0,s,0);
            o[0]=1,o[1]=0,o[2]=2;
            dfs(0,s,0);
            o[0]=1,o[1]=2,o[2]=0;
            dfs(0,s,0);
            o[0]=2,o[1]=0,o[2]=1;
            dfs(0,s,0);
            o[0]=2,o[1]=1,o[2]=0;
            dfs(0,s,0);
            ans=min(ans,abs(s-t));
            LL p=ans,q=i;
            res=(res+q*p%N)%N;
        }
        printf("%I64d
",res);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5246791.html