Codeforces 831D Office Keys————DP/二分

题解:本题主要考查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[i1][j1],abs(a[j]key[i])+abs(pkey[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[i1][j],max(dp[i1][j1],abs(a[j]key[i]+pkey[i])));
代码如下:

#include
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)