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

Portal

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

题目大意

从点1出发,你要按顺序完成k个任务,每个任务有要求的起点终点。
途中你可以在所在的位置建立一个传送门,而同时只能用两个传送门存在,如果超过两个,则必须(远程)关闭任意一个传送门。

解题思路

首先可以想到,所谓的k个任务有起点终点,就是按顺序走过2k个点,a->b,c->d这样的两个任务,可以转化为走过1->a->b->c->d这条路径。
先想到一种暴力操作,每次求出dp[i][x][a][b],表示已经完成i个任务,当前在x点,传送门分别在a,b。

如果我们要使用传送门来少走点路,肯定是走到一个接近x的传送门,在传送到接近终点的传送门。
但是直接在x建立一个传送门岂不是更偷懒,所以我们不必记录两个传送门,只需记录远的一个即可。这样就可以简化为dp[i][x][b]。

脑袋一拍,现在所在的点x也不用记录,我们在输入时将节点排成一行(就是第一句的思想),用数组a记录每个点;所以又可以简化为dp[i][b](当前在a[i])。
每次任务都枚举上一次任务留下的传送门位置,和这次传送门放在哪里来状态更新。

可以简化得到三种状态转移:(有点复杂)

  • 直接从a[i]走到a[i+1];
  • 枚举走到a[i+1]后传送门的位置,设它的位置为t。
    从a[i]走到t,将传送门放在t,再从t传送到b(另一个传送门),走到a[i+1];
  • 从a[i]传送到b,在从b走到t,将传送门放在t,再从t走到啊a[i+1]。

按照上面的做法,直接先用Floyd的思路求最短路,再加dp即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
long long g[310][310],dp[610][610],ans=1e16,z;
int a[610],n,m,k;
int main()
{
    int t=1,x,y,i,j;
    scanf("%d%d%d",&n,&m,&k);
    a[1]=1;
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(i==j) g[i][j]=0;
            else g[i][j]=1e16;
    for(i=2;i<=n;i++) dp[1][i]=1e16;
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%lld",&x,&y,&z);
        g[x][y]=g[y][x]=min(g[x][y],z);
    }
    for(i=1;i<=k;i++)
    {
        scanf("%d%d",&x,&y);
        a[++t]=x,a[++t]=y;
    }
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            for(k=1;k<=n;k++)
                if(g[i][j]+g[i][k]<g[j][k])
                    g[j][k]=g[i][j]+g[i][k];
    for(i=2;i<=t;i++)
    {
        for(j=0;j<=n;j++) dp[i][j]=1e16;
        x=a[i-1],y=a[i];
        for(j=1;j<=n;j++)
        {
            dp[i][x]=min(dp[i][x],dp[i-1][j]+min(g[x][y],g[j][y]));
            dp[i][j]=min(dp[i][j],dp[i-1][j]+min(g[x][y],g[j][y]));
            for(k=1;k<=n;k++)
                dp[i][k]=min(dp[i][k],min(dp[i-1][j]+g[j][k]+g[k][y],dp[i-1][j]+g[x][k]+g[k][y]));
        }
    }
    for(i=1;i<=n;i++) ans=min(ans,dp[t][i]);
    printf("%lld\n",ans);
    return 0;
}
2020牛客暑期多校训练营 文章被收录于专栏

只是题解,可参考,可学习,可点赞:)

全部评论

相关推荐

smile丶snow:项目完成时间要写一个大概的区间,自己顺延一下就行。感觉ai对话的放第一个比较好。可以自己编一些场景或者找ai编一个场景。就是你为什么要写这个仿DeepSeek对话应用。比如你自己有很多文档,这个ai可以基于你自己的文档回答之类的。个人建议~具体看你自己。 还有项目中用到那些更好让ai coding的方法也可以写一下,毕竟现在ai大跃进…
简历被挂麻了,求建议
点赞 评论 收藏
分享
04-02 10:09
门头沟学院 Java
用微笑面对困难:这里面问题还是很多的,我也不清楚为啥大家会感觉没啥问题。首先就是全栈开发实习9个月的内容都没有java实习生的内容多,1整个技术栈没看出太核心和难点的内容,感觉好像被拉过去打杂了,而且全栈基本上很容易被毙。里面能问的bug是在太多了比如L:继承 BaseMapper 可直接使用内置方法’。请问你的 BaseMapper 是如何扫描实体类注解如果瞬时产生 100 个上传任务,MySQL 的索引设计是否会有瓶颈?你做过分库分表或者索引优化吗?全栈的内容可以针对动态难点去搞,技能特长写在下面吧,你写了这么多技能,项目和实习体现了多少?你可以在项目里多做文章然后把这个放下去,从大致来看实习不算太水,有含金量你也要写上内容针对哨兵里面的节点变化能问出一万个问题,这个很容易就爆了。
提前批简历挂麻了怎么办
点赞 评论 收藏
分享
评论
5
1
分享

创作者周榜

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