洛谷 P2339 & USACO2004Open 提交作业 题解

该博客详细解析了一道关于数轴上规划路径以最小化交作业和到达车站总时间的问题。作者首先介绍了题目背景和数据格式,接着探讨了两种尝试的解决方案:排序后的暴力搜索和动态规划,但都遇到了问题。最后,作者提出了一个改进的动态规划策略,并给出了转移方程,用于计算最短时间。代码实现也作为辅助理解提供。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意简述

一个数轴长 H H H单位,有 C C C个办公室,其中位置在 x i x_i xi,在 t i t_i ti时刻后开放,珂以交作业。公交车站在 B B B位置。一开始 B e s s i e Bessie Bessie站在 0 0 0位置,一个时刻珂以移动一个单位。帮 B e s s i e Bessie Bessie合理规划,使得她交完所有作业并赶往车站总时间最小。

数据

输入

第一行三个正整数 C , H , B C,H,B C,H,B(三个都 &lt; = 1000 &lt;=1000 <=1000 b &lt; = H b&lt;=H b<=H
接下来 C C C行每行两个正整数 x i , t i x_i,t_i xi,ti(两个都 &lt; = 10000 &lt;=10000 <=10000),意义见描述。

输出

一个整数,最短用时。

思路

先把每个办公室按位置从小到大排序,显然,不然没的处理。
接下来,爆搜。。。好像不行。。。

尝试 D P DP DP。套路的,我们设 d p [ l ] [ r ] dp[l][r] dp[l][r]为从第 l l l个办公室到第 r r r个办公室的最短时间。会发现一个问题:没法转移了。因为我们需要知道上一个状态是由哪个办公室转移过来的,然后求一下距离。然后我们转移到哪个办公室呢? [ l , r ] [l,r] [l,r]之间都有珂能,所以这样的 D P DP DP就是 O ( n 3 ) O(n^3) O(n3)了,甚至更多(我还么继续考虑下去呢!)。比爆搜多写了很多代码,还和爆搜的分拿的一样,不值得。

上一个思路失败就失败在没定下来转移到哪个点。这次,我们尝试强人锁♂男, d p [ l ] [ r ] [ 0 / 1 ] dp[l][r][0/1] dp[l][r][0/1]表示第 [ l , r ] [l,r] [l,r]个办公室之间,以 l / r l/r l/r / / /表示"或")为结尾的最优解。这样是好转移了,是 O ( 1 ) O(1) O(1)的转移,但是这样得到的答案就是 [ 1 , c ] [1,c] [1,c]个办公室中以 1 / c 1/c 1/c结尾+到车站的距离的最优答案。万一我们以中间某个点结尾就是最优答案呢?不久考虑不到了么?一交, W A WA WA了,能不能骗到部分分我不知道(没试过),反正不确定性还是很大的,还需要改进。

我们只要改进一点点:把刚刚的状态反选(会做图片的同学珂能知道反选是什么), d p [ l ] [ r ] [ 0 / 1 ] dp[l][r][0/1] dp[l][r][0/1]表示 [ l , r ] [l,r] [l,r]之间的办公室 不 交 作 业 \color{red}不交作业 ,其他都交,再交上第 l / r l/r l/r个办公室的作业,的最优解。如果认真思考了上面的思路(我没有给出转移方程),就会不难得到这个思路的大概转移:

min(( [ l − 1 , r ] [l-1,r] [l1,r]的答案+ l − 1 l-1 l1 l l l的距离),( [ l , r + 1 ] [l,r+1] [l,r+1]的答案+ r + 1 r+1 r+1 l l l的距离))更新 d p [ l ] [ r ] [ 0 ] , dp[l][r] [0], dp[l][r][0]
min(( [ l − 1 , r ] [l-1,r] [l1,r]的答案+ l − 1 l-1 l1 r r r的距离),( [ l , r + 1 ] [l,r+1] [l,r+1]的答案+ r + 1 r+1 r+1 r r r的距离))更新 d p [ l ] [ r ] [ 1 ] dp[l][r] [1] dp[l][r][1]
答案就是 m i n { d p [ i ] [ i ] [ 0 ] + ∣ i − B ∣ } min\{dp[i][i][0]+|i-B|\} min{dp[i][i][0]+iB}
Q Q Q:既然取答案的时候只用到了 d p [ i ] [ i ] [ 0 ] dp[i][i][0] dp[i][i][0],那么:)
(1. d p [ i ] [ i ] [ 0 ] dp[i][i][0] dp[i][i][0]是否等于 d p [ i ] [ i ] [ 1 ] dp[i][i][1] dp[i][i][1]呢?)
(2. 如果等于,说明我们只用到了其中一个,为什么还要写两个呢?)
A : A: A:
(1. 等于的,都是 [ i , i ] [i,i] [i,i]的作业不交,再交上 i i i的作业,即全部交上的情况)
(2. 虽然取答案只用一个,但是如果转移的时候少考虑一个就会导致答案不正确)
代码:

#include<bits/stdc++.h>
using namespace std;
namespace Flandle_Scarlet
{
    #define N 1010
    struct office
    {
        int x,t;
    }off[N];bool operator<(office a,office b){return a.x<b.x;}
    int c,h,b;
    void Input()
    {
        scanf("%d%d%d",&c,&h,&b);
        for(int i=1;i<=c;++i)
        {
            scanf("%d%d",&off[i].x,&off[i].t);
        }
        sort(off+1,off+c+1);
    }

    int dp[N][N][2];
    void up(int &x,int y)
    //用y更新x的最小值
    {
        x=min(x,y);
    }
    void DP()
    {
        memset(dp,0x3f,sizeof(dp));
        dp[1][c][0]=max(off[1].x,off[1].t);
        dp[1][c][1]=max(off[c].x,off[c].t);

        for(int l=1;l<=c;++l)
        {
            for(int r=c;r>=l;--r)
            {
                up(dp[l][r][0],max(dp[l-1][r][0]+(off[l].x-off[l-1].x),off[l].t));
                up(dp[l][r][0],max(dp[l][r+1][1]+(off[r+1].x-off[l].x),off[l].t));
                up(dp[l][r][1],max(dp[l-1][r][0]+(off[r].x-off[l-1].x),off[r].t));
                up(dp[l][r][1],max(dp[l][r+1][1]+(off[r+1].x-off[r].x),off[r].t));
                //转移方程
            }
        }

        int ans=0x3f3f3f3f;
        for(int i=1;i<=c;++i)
        {
            up(ans,dp[i][i][1]+abs(b-off[i].x));
            //上面说了dp[i][i][0]==dp[i][i][1],所以此处写成dp[i][i][0]也珂以过
        }
        printf("%d\n",ans);
    }
    void Main()
    {
        if (0)
        {
            freopen("","r",stdin);
            freopen("","w",stdout);
        }
        Input();
        DP();
    }
    #undef N//1010
};
main()
{
    Flandle_Scarlet::Main();
    return 0;
}

回到总题解界面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值