CF Round 424 D Offices Keys (贪心)
题目链接:http://codeforces.com/contest/831/problem/D
思路:由于拿到钥匙之后需要走的路程是确定的,因此关键在于如何选择钥匙。对于最靠近P位置的人来说,拿最接近P且同侧的钥匙是最划算的。
因此二分答案,每次check的时候从小到大判断对于所有的人是否都能在时限内进入office即可。
另外也可以使用动态规划 dp[i][j]:前j个钥匙中i个人拿走i把所需的时间,则
dp[i][j] = max(dp[i - 1][j - 1], abs(a[i] - b[j])+abs(b[j] - p)) i == j
dp[i][j] = min(dp[i][j - 1], max(dp[i - 1][j - 1], abs(a[i] - b[j])+abs(b[j] - p))) i < j
需要注意无论二分还是dp都需要先排序
代码:
二分:
1 #define maxn 2010 2 int n, k, p; 3 int a[maxn], b[maxn]; 4 5 bool check(long long x){ 6 int st = 0; 7 for(int i = 0; i < n; i++){ 8 bool flag = false; 9 for(int j = st; j < k; j++){ 10 if(abs(p - b[j]) + abs(a[i] - b[j]) <= x){ 11 flag = true; 12 st = j + 1; 13 break; 14 } 15 } 16 if(!flag) return false; 17 } 18 return true; 19 } 20 21 22 int main(){ 23 scanf("%d %d %d", &n, &k, &p); 24 for(int i = 0; i < n; i++){ 25 scanf("%d", &a[i]); 26 } 27 for(int i = 0; i < k; i++){ 28 scanf("%d", &b[i]); 29 } 30 sort(a, a + n); 31 sort(b, b + k); 32 long long l = 0, r = 2e15; 33 while(l < r){ 34 long long mid = (l + r) / 2; 35 if(check(mid)){ 36 r = mid; 37 } 38 else{ 39 l = mid + 1; 40 } 41 } 42 printf("%lld\n", l); 43 }
DP:
1 #define maxn 2010 2 #define inf 0x3f3f3f3f3f3f3f3f 3 int n, k, p; 4 long long a[maxn], b[maxn]; 5 long long dp[maxn][maxn]; 6 7 int main(){ 8 scanf("%d %d %d", &n, &k, &p); 9 for(int i = 1; i <= n; i++){ 10 scanf("%lld", &a[i]); 11 } 12 for(int i = 1; i <= k; i++){ 13 scanf("%lld", &b[i]); 14 } 15 memset(dp, 0, sizeof(dp)); 16 sort(a + 1, a + n + 1); 17 sort(b + 1, b + k + 1); 18 19 for(int i = 1; i <= n; i++){ 20 for(int j = i; j <= k; j++){ 21 if(i == j){ 22 dp[i][j] = max(dp[i - 1][j - 1], abs(a[i] - b[j]) + abs(p - b[j])); 23 } 24 else dp[i][j] = min(dp[i][j - 1], max(dp[i - 1][j - 1], abs(p - b[j]) + abs(a[i] - b[j]))); 25 // debug 26 // printf("%d %d:%lld\n", i, j, dp[i][j]); 27 } 28 } 29 long long ans = dp[n][k]; 30 for(int i = n; i <= k; i++){ 31 ans = min(ans, dp[n][i]); 32 } 33 printf("%lld\n", ans); 34 }
题目: