题意简述
一个数轴长 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(三个都
<
=
1000
<=1000
<=1000且
b
<
=
H
b<=H
b<=H)
接下来
C
C
C行每行两个正整数
x
i
,
t
i
x_i,t_i
xi,ti(两个都
<
=
10000
<=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]
[l−1,r]的答案+
l
−
1
l-1
l−1到
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]
[l−1,r]的答案+
l
−
1
l-1
l−1到
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]+∣i−B∣}。
(
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;
}