• cf831D(dp)


    题目链接: http://codeforces.com/contest/831/problem/D

    题意: 有 n 个人和 k 把钥匙, 数组 a 为 n 个人的初始位置, 数组 b 为 k 把钥匙的初始位置, n 个人都要先拿到一把钥匙然后在到 p 位置去, 问所有人都到 p 位置所需要的最少时间是多少.

    思路: 这题即可以 dp 也可以直接二分答案.

    dp 思路为: dp[i][j]存储前i个人在前j把钥匙中每个人得到钥匙的最小花费.

    那么动态转移方程式为:

      if(i == j) dp[i][j] = max(dp[i - 1][j - 1], abs(a[i] - b[j]) + abs(p - b[j]))

      else if(j > i) dp[i][j] = min(dp[i][j - 1], max(dp[i - 1][j - 1], abs(a[i] - b[j]) + abs(p - b[j])))

    代码:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <stdio.h>
     4 using namespace std;
     5 
     6 const int MAXN = 1e3 + 10;
     7 int a[MAXN], b[MAXN << 1], dp[MAXN][MAXN << 1];//dp[i][j]存储前i个人在前j把钥匙中每个人得到钥匙的最小花费
     8 
     9 int main(void){
    10     int n, k, p;
    11     scanf("%d%d%d", &n, &k, &p);
    12     for(int i = 1; i <= n; i++){
    13         scanf("%d", &a[i]);
    14     }
    15     for(int i = 1; i <= k; i++){
    16         scanf("%d", &b[i]);
    17     }
    18     sort(a + 1, a + n + 1);
    19     sort(b + 1, b + k + 1);
    20     for(int i = 1; i <= n; i++){
    21         for(int j = i; j <= k; j++){
    22             if(i == j) dp[i][j] = max(dp[i - 1][j - 1], abs(b[j] - a[i]) + abs(p - b[j]));
    23             else dp[i][j] = min(dp[i][j - 1], max(dp[i - 1][j - 1], abs(b[j] - a[i]) + abs(p - b[j])));
    24         }
    25     }
    26     int sol = 2e9 + 10;
    27     for(int i = n; i <= k; i++){
    28         sol = min(sol, dp[n][i]);
    29     }
    30     printf("%d
    ", sol);
    31     return 0;
    32 }
    View Code
  • 相关阅读:
    1360 奇怪的电梯(lift)
    1249 Lake Counting
    1330 【例8.3】最少步数
    1329 【例8.2】细胞
    1215 迷宫
    垃圾树
    vector
    1970:【15NOIP普及组】扫雷游戏
    1251:仙岛求药
    Python3+PCAN-USB基于PCAN-Basic二次开发实现上位机功能
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7181935.html
Copyright © 2020-2023  润新知