Codeforces - 831D. Office Keys - dp、二分+贪心

D. Office Keys

题目链接

分类:dp、二分、贪心

1.题意概述

  • 一个坐标轴上有n个人,他们坐标分别为 a[1...n] ,而且有k把钥匙坐标分别在 b[1...k] ,现在办公室们在坐标为p的位置,每个人必须要拿到唯一一把钥匙进入办公室们,不同人之间不能共用,问你所有人进入办公室的最短时间是多少?
  • 数据范围 1n1000,nk2000,1p109,1ai109,1bj109

2.解题思路

  • 我们分别读入 a[1...n] b[1...k] ,排序后观察,对于 aiaj bkbm ,如果将这两把钥匙分配给这两个人,要分配方式最优只可能 aibk,ajbm ,因为如果 aibm,ajbk ,那么最大的花费时间是 max(|aibm|+|bmp|,|ajbk|+|bkp|) ,显然小于前者 max(|aibk|+|bkp|,|ajbm|+|bmp|) ,白话去理解就是离门最近的人去拿最远的钥匙是不可取的
    • 有了这个性质,我们容易发现这就符合线性dp的最优子结构啊,然后n和k的数据范围也很开心,复杂度 O(nk)
    • 当然根据这样分配性质,我们也完全可以考虑二分答案+贪心分配,每个人都去取离他最左侧钥匙就行!这样做复杂度 O(nklogm) 其中 m 是钥匙最大长度。

3.AC代码

dp代码

#include 
#define INF 0x7fffffff
#define maxn 100010
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r - t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
#define Close() ios::sync_with_stdio(0),cin.tie(0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
int a[N], b[N << 1], dp[N][N << 1];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    long _begin_time = clock();
#endif
    int n, k, p;
    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", &b[i]);
    sort(a + 1, a + n + 1);
    sort(b + 1, b + k + 1);
    dp[0][0] = 0;
    for (int i = 1; i <= k; i++)
        dp[0][i] = 0;
    for (int i = 1; i <= n; i++)
    {
        dp[i][0] = INF;
        for (int j = 1; j <= k; j++)
            dp[i][j] = max(abs(a[i] - b[j]) + abs(b[j] - p), dp[i - 1][j - 1]);
        for (int j = 1; j <= k; j++)
            dp[i][j] = min(dp[i][j], dp[i][j - 1]);
    }
    printf("%d\n", dp[n][k]);
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}

二分代码

#include 
#define INF 0x7fffffff
#define maxn 100010
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r - t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
#define Close() ios::sync_with_stdio(0),cin.tie(0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
int a[N], b[N << 1], n, k, p;
bool check(ll x)
{
    int cnt = 0, next = 1;
    for (int i = 1; i <= n; i++)
        for (int j = next; j <= k; j++)
            if (abs(a[i] - b[j]) + abs(b[j] - p) <= x)
            {
                next = j + 1;
                cnt++;
                break;
            }
    return cnt == n;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    long _begin_time = clock();
#endif

    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", &b[i]);
    sort(a + 1, a + n + 1);
    sort(b + 1, b + k + 1);
    ll l = -1, r = INF, ans = 0;
    while (l <= r)
    {
        ll mid = l + r >> 1;
        if (check(mid))
        {
            ans = mid;
            r = mid - 1;
        }
        else
            l = mid + 1;
    }
    printf("%I64d\n", ans);
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}

你可能感兴趣的:(Codeforces,动态规划(DP),二分,贪心)