2020牛客暑期多校训练营(第五场)A

Portal

https://ac.nowcoder.com/acm/contest/5670/A

题目描述

  You are now in a big factory. The factory could be recognized as a graph with n vertices and m edges. Every edge has its length. You have missions to do. The -th mission is going to vertex , picking a block and then sending it to vertex . You should complete the missions in the order from -st to -th. Initially you are standing at vertex .
  You have a gun in your hand. When you are at some vertex , you could shoot the gun at the ground, and then a portal will be built at vertex . When there are two portals in the factory, assuming they are at and , you could transfer between and with no cost (just like an edge connecting and with length ).
  You also have a remote controller in your hand. It allows you to close a portal whenever you want and wherever you are (closing one portal at a time, not all portals at the same time). What's more, there could be at most two existing portals. So if you want to create another portal when there exists two, you must use your controller to close one before you create.
  You need to find the minimum distance you have to walk in order to complete all missions.

输入描述

  First line contains three positive integers separated by spaces.
  Next lines, each contains three integers , indicating a bidirectional edge connecting vertex and with length .
  Next lines, each contains two intergers , indicating the begin and the end of the -th mission.
  , , .
  , .
  .
  The graph is guaranteed to be connected.

输出描述

  Output one integer indicating the minimum distance.

示例1

输入

5 4 2
1 2 1
2 3 1
3 4 1
4 5 1
1 5
2 4

输出

5

说明

  Solution for sample : walk from to , create portals at and when passing by, and then walk from to , then you could use portals to complete the second mission.

示例2

输入

6 10 3
1 1 6
5 6 9
3 5 8
1 4 1
2 4 7
6 6 10
1 4 2
6 5 10
3 5 2
3 1 9
1 5
2 5
4 3

输出

28

示例3

输入

6 10 3
1 1 3
3 1 1
6 2 3
1 6 10
4 1 1
3 1 2
5 6 9
5 4 10
6 3 4
3 4 4
3 5
3 6
6 5

输出

16

分析

  用动态规划求解。
   表示已经完成了第 个任务,当前人在节点 ,传送门在节点 时,行走的最短距离。状态过多,显然会
  贪心地思考,一直创建两个传送门是没有必要的:若要从 传送到 ,当前节点为 ,那么必须要从 走到 再传送到 ;不妨只在 创建一个传送门,走到 后再设置传送门;也就是说,我们可以随时在当前节点创建传送门。因此,只需要在状态中记录一个传送门的位置即可。 表示已经完成了第 个任务,当前人在节点 ,传送门在节点 时,行走的最短距离。需要继续精简状态。
  不妨将 个任务看作一条路径:。一共有 个节点, 表示第 个节点,其中 表示当前人位于节点 ,传送门位于节点 时,行走的最短距离。
  可以证明,只需要三种转移,即可覆盖所有状态:① 直接从 走到 ,不更改传送门位置;② 枚举 ,将传送门的位置更改到 ,从 传送到 ,再从 走到 ,将传送门放在 ,再从 走到 ;③ 枚举 ,将传送门的位置更改到 ,从 走到 ,将传送门放在 ,再从 传送到 ,从 走到

代码

/******************************************************************
Copyright: 11D_Beyonder All Rights Reserved
Author: 11D_Beyonder
Problem ID: 2020牛客暑期多校训练营(第五场) Problem A
Date: 8/24/2020
Description: Dynamic Programming
*******************************************************************/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int N=705;
//====================
//f[i][j]表示:
// 当前在c[i],传送门在j时;
// 行走的最小路程。
ll f[N][N];
ll dis[N][N];
int c[N];
int n,m;
int t;
int main(){
    int i,j,k;
    cin>>n>>m>>k;
    memset(f,inf,sizeof(f));
    memset(dis,inf,sizeof(dis));
    for(i=1;i<=n;i++) dis[i][i]=0;
    for(i=1;i<=m;i++){
        int u,v;
        ll w;
        scanf("%d%d%lld",&u,&v,&w);
        dis[u][v]=min(dis[u][v],w);
        dis[v][u]=min(dis[v][u],w);
    }
    c[++t]=1;
    for(i=1;i<=k;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        c[++t]=a;
        c[++t]=b;
    }
    //Floyed算法求(x,y)之间的最短路
    for(k=1;k<=n;k++){
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++){
                dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
            }
        }
    }
    for(i=1;i<=n;i++){
        //初始化
        //当前在c[1]
        //传送门设置在i
        f[1][i]=dis[1][i];
    }
    int p,q;
    for(i=2;i<=t;i++){
        //当前在c[i-1],要走向c[i]
        for(p=1;p<=n;p++){
            //当前传送门在p
            //不改变传送门位置,直接走到 c[i]
            f[i][p]=min(f[i][p],f[i-1][p]+dis[c[i-1]][c[i]]);
            for(q=1;q<=n;q++){
                //从c[i-1]传送到p,路程0
                //从p走到q,路程dis[p][q]
                //从q走到a[i],路程dis[q][c[i]]
                f[i][q]=min(f[i][q],f[i-1][p]+dis[p][q]+dis[q][c[i]]);
                //从c[i-1]走到q,路程dis[c[i-1]][q]
                //从q传送到p,路程为0
                //从p走到c[i],路程dis[q][c[i]]
                f[i][q]=min(f[i][q],f[i-1][p]+dis[c[i-1]][q]+dis[p][c[i]]);
            }
        }
    }
    ll ans=inf;
    for(i=1;i<=n;i++){
        ans=min(f[t][i],ans);
    }
    cout<<ans<<endl;
    return 0;
}
牛客暑期多校训练营题解 文章被收录于专栏

收集牛客暑期多校训练营的题解

全部评论

相关推荐

叶扰云倾:进度更新,现在阿里云面完3面了,感觉3面答得还行,基本都答上了,自己熟悉的地方也说的比较细致,但感觉面试官有点心不在焉不知道是不是不想要我了,求阿里收留,我直接秒到岗当阿里孝子,学校那边的房子都退租了,下学期都不回学校,全职猛猛实习半年。这种条件还不诱人吗难道 然后现在约到了字节的一面和淘天的复活赛,外加猿辅导。华为笔试完没动静。 美团那边之前投了个base广州的,把我流程卡麻了,应该是不怎么招人,我直接简历挂了,现在进了一个正常的后端流程,还在筛选,不知道还有没有hc。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务