题解:本题主要考查DP/二分。
简要题意:给你nnn个人,有kkk把钥匙,终点为mmm.每个人要求拿一把钥匙到终点,问多长时间,能够使得所有人都到达。
把所有人的位置以及钥匙的位置全部sort一遍,
1.二分:排序后,前一个去的钥匙位置一定在后一个人取得钥匙前面,否则交叉浪费时间。然后二分最长时间,从左向右验证。
2.DP:设dp[i][k]dp[i][k]dp[i][k]表示前iii个人,前jjj把钥匙中都拿到了钥匙,并且到终点的最优时间。
(1):i==ji==ji==j时,拿上钥匙:
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]))dp[i][j]=max(dp[i−1][j−1],abs(a[j]−key[i])+abs(p−key[i])),
absabsabs内的表示第iii个人拿到第jjj把钥匙到终点所需路程
(2):else
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])));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;
}
本文探讨了一个涉及动态规划(DP)与二分查找的算法问题,目标是最小化n个人拿到k把钥匙并抵达终点所需的时间。通过排序、二分查找优化路径选择及DP状态转移方程,实现高效求解。

461

被折叠的 条评论
为什么被折叠?



