【CodeForces】704 B. Ant Man「建议收藏」

【CodeForces】704 B. Ant Man

大家好,又见面了,我是全栈君。

【题目】B. Ant Man

【题意】给定n个人的xi,ai,bi,ci,di,起点为s,终点为e,移动:

In simpler words, jumping from i-th chair to j-th chair takes exactly:

  • |xi - xj| + ci + bj seconds if j < i.
  • |xi - xj| + di + aj seconds otherwise (j > i).

求中间经过所有点恰好一次的最小代价。

【算法】动态规划

【题解】很巧妙的DP状态设计。(这样类似哈密顿路径的问题不能从图论方面考虑,否则很容易变成NP问题)

将代价拆分到每个点:

向左,起c+x,落b-x

向右,起d-x,落a+x

那么对于前i个点,有效信息只有这i个点中缺少多少入边和缺少多少出边。先无视s(起点)和t(终点),那么缺入边数和缺出边数相等。

令f[i][j]表示前i个点中缺少j条入/出边的最小代价,缺少入边的本质是被往左,缺少出边的本质是往右。

对于f[i-1][j],有以下四种转移:

被往右+往右:j>0,f[i][j]=f[i-1][j]+a[i]+d[i](两个x[i]抵消)——减少一条出边,同时增加一条出边

往左+被往左:j>0,f[i][j]=f[i-1][j]+b[i]+c[i]——减少一条入边,同时增加一条入边

被往右+往左:j>0,f[i][j-1]=f[i-1][j]+a[i]+c[i]+2*x[i]——减少一条入边和一条出边

往右+被往左:f[i][j+1]=f[i-1][j]+b[i]+d[i]-2*x[i]——增加一条入边和一条出边

最终答案为f[n][0]。

接下来解决s和t的问题,实际上s和t才能代表一个完整的点,所以将s当成一个完整的点,不把t看作一个点。

先经过s:会多一条不该有的入边,所以只要避免第二个和第三个转移。

先经过t:会少一条该有的入边,所以只要在j=0时强制进行第二个转移。

最后在到达n之前和st均有或均无时,不能成环,强制f[i][0]=inf。

复杂度O(n^2)。

【CodeForces】704 B. Ant Man「建议收藏」
【CodeForces】704 B. Ant Man「建议收藏」

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll inf=1e16,maxn=5010;
ll f[maxn][maxn];
int n,s,t,x[maxn],a[maxn],b[maxn],c[maxn],d[maxn];
void m(ll &a,ll b){
    
    if(a>b)a=b;}
ll solve(){
    memset(f,0x3f,sizeof(f));
    int tot=0;f[0][0]=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<=i;j++)if(f[i-1][j]<inf){
            int S=j,T=S+tot;
            if(i==s){
                if(T)m(f[i][j],f[i-1][j]+c[i]+x[i]);
                m(f[i][j+1],f[i-1][j]+d[i]-x[i]);
            }
            else if(i==t){
                if(S)m(f[i][j-1],f[i-1][j]+a[i]+x[i]);
                m(f[i][j],f[i-1][j]+b[i]-x[i]);
            }
            else{
                if(S)m(f[i][j],f[i-1][j]+a[i]+d[i]);
                if(T)m(f[i][j],f[i-1][j]+b[i]+c[i]);
                if(S&&T)m(f[i][j-1],f[i-1][j]+a[i]+c[i]+2*x[i]);
                m(f[i][j+1],f[i-1][j]+b[i]+d[i]-2*x[i]);
            }
        }
        if(i==s)tot--;if(i==t)tot++;
        if(i!=n&&tot==0)f[i][0]=inf;
    }
    return f[n][0];
}
int main(){
    scanf("%d%d%d",&n,&s,&t);
    for(int i=1;i<=n;i++)scanf("%d",&x[i]);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    for(int i=1;i<=n;i++)scanf("%d",&d[i]);
    printf("%lld",solve());
    return 0;
}

View Code

 

PS:我在这场比赛进行Virtual participation的时候,大力贪心出B……然后排名好高啊><。

至今无人能证明但AC了的贪心(似乎有人给反例):初始s-t,然后考虑一个一个点找最优位置插入。

转载于:https://www.cnblogs.com/onioncyc/p/8277875.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107759.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql 删除一条数据sql语句_sql删除语句[通俗易懂]

    mysql 删除一条数据sql语句_sql删除语句[通俗易懂]sql删除语句一般简单的删除数据记录用delete就行了,但是如何要删除复杂的外键就不是一条delete删除来实例的,我们本文章先讲一下delete删除,然后再告诉你利用触发器删除多条记录多个表。删除数据库中的数据sql删除语句一般简单的删除数据记录用delete就行了,但是如何要删除复杂的外键就不是一条delete删除来实例的,我们本文章先讲一下delete删除,然后再告诉你利用触发器删除多…

    2022年9月1日
    4
  • oracle罗马字符转数字,一些关于罗马字符的知识

    oracle罗马字符转数字,一些关于罗马字符的知识I=1V=5X=10L=50C=100D=500M=1000下面是关于构造罗马数字的一些通用的规则的介绍:字符是叠加的。I表示1,II表示2,而III表示3。VI表示6(字面上为逐字符相加,“5加1”),VII表示7,VIII表示8。含十字符(I、X、C和M)至多可以重复三次。对于4,你则需要利用下一个最大的含五字符进行减操作得…

    2022年9月30日
    3
  • Linux —— useradd -g mysql mysql解析及useradd详解

    Linux —— useradd -g mysql mysql解析及useradd详解当我们在不通过 yum CentOS apt get Ubuntu 来安装 MySQL 的时候 通常执行以下命令来创建一个用户名为 mysql 的用户并加入 mysql 用户组 root localhost useradd gmysqlmysql 那 这两个 mysql 谁是用户名谁是用户组呢 事实上它还可以这样写 root localhost

    2025年8月9日
    3
  • ClientHeight_offsetheight获取高度不对

    ClientHeight_offsetheight获取高度不对clientHeight:包括padding但不包括border、水平滚动条、margin的元素的高度。对于inline的元素这个属性一直是0,单位px,只读元素。offsetHeight:包括padding、border、水平滚动条,但不包括margin的元素的高度。对于inline的元素这个属性一直是0,单位px,只读元素。style.height//返回元素的高度(包括元素高度,不包括内边距、边框和外边距)clientHeight//返回元素的高度(包括元素高度、

    2025年10月23日
    3
  • javascript获取当前系统时间代码_获取当前系统时间

    javascript获取当前系统时间代码_获取当前系统时间JavaScript获取当前时间time开发常用时间笔记JS获取当前时间Js获取当前日期时间及其它操作**谨记要懂得经常在控制台输出结果**varmyDate=newDate();myDate.getYear();//获取当前年份(2位)myDate.getFullYear();//获取完整的年份(4位,1970-???)myDate.getMonth();//获取当前月份(0-11,0代表1月)myDate.getDate();

    2022年9月23日
    1
  • pycharm怎么装第三方库jieba_pycharm找不到第三方库

    pycharm怎么装第三方库jieba_pycharm找不到第三方库第一种想要安装什么库,就直接cmd打开pipinstall库,这种方法可以的,不过速度会有点慢不过,有时候失败就难受。第二种直接在pycharm中安装如图,不过安装失败的情况比较多(可能是我电脑问题)第三种下载了Anaconda的小伙伴,虽然conda里面含有很多库了,但是还有需要下载的就可以直接打开AnacondaNavigator,在里面进行操作,如图四、上面三种都不行有安装Anaconda的话,直接上网搜索库名加pypi..

    2022年8月29日
    8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号