题解:本题主要考查DP/二分。
简要题意:给你
n
n
n个人,有
k
k
k把钥匙,终点为
m
m
m.每个人要求拿一把钥匙到终点,问多长时间,能够使得所有人都到达。
把所有人的位置以及钥匙的位置全部sort一遍,
1.二分:排序后,前一个去的钥匙位置一定在后一个人取得钥匙前面,否则交叉浪费时间。然后二分最长时间,从左向右验证。
2.DP:设
d
p
[
i
]
[
k
]
dp[i][k]
dp[i][k]表示前
i
i
i个人,前
j
j
j把钥匙中都拿到了钥匙,并且到终点的最优时间。
(1):
i
=
=
j
i==j
i==j时,拿上钥匙:
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
1
]
[
j
−
1
]
,
a
b
s
(
a
[
j
]
−
k
e
y
[
i
]
)
+
a
b
s
(
p
−
k
e
y
[
i
]
)
)
dp[i][j]=max(dp[i-1][j-1],abs(a[j]-key[i])+abs(p-key[i]))
dp[i][j]=max(dp[i−1][j−1],abs(a[j]−key[i])+abs(p−key[i])),
a
b
s
abs
abs内的表示第
i
i
i个人拿到第
j
j
j把钥匙到终点所需路程
(2):else
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
−
1
]
[
j
]
,
m
a
x
(
d
p
[
i
−
1
]
[
j
−
1
]
,
a
b
s
(
a
[
j
]
−
k
e
y
[
i
]
+
p
−
k
e
y
[
i
]
)
)
)
;
dp[i][j]=min(dp[i-1][j],max(dp[i-1][j-1],abs(a[j]-key[i]+p-key[i])));
dp[i][j]=min(dp[i−1][j],max(dp[i−1][j−1],abs(a[j]−key[i]+p−key[i])));
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,k,p;
int dp[6666][6666];
int a[6666],key[6666];
int main()
{
scanf("%d %d %d",&n,&k,&p);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
for(int i=1;i<=k;++i)scanf("%d",&key[i]);
sort(a+1,a+1+n);
sort(key+1,key+1+k);
memset(dp,0,sizeof(dp));
for(int i=1;i<=k;++i)
{
for(int j=1;j<=n;++j)
{
if(i==j)dp[i][j]=max(dp[i-1][j-1],abs(a[j]-key[i])+abs(p-key[i]));
else dp[i][j]=min(dp[i-1][j],max(dp[i-1][j-1],abs(a[j]-key[i])+abs(p-key[i])));
}
}
printf("%d",dp[k][n]);
return 0;
}