codeforces830A (二分|DP)

来源:互联网 发布:数据库添加语句 编辑:程序博客网 时间:2024/04/27 10:29

A. Office Keys
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are n people and k keys on a straight line. Every person wants to get to the office which is located on the line as well. To do that, he needs to reach some point with a key, take the key and then go to the office. Once a key is taken by somebody, it couldn't be taken by anybody else.

You are to determine the minimum time needed for all n people to get to the office with keys. Assume that people move a unit distance per 1 second. If two people reach a key at the same time, only one of them can take the key. A person can pass through a point with a key without taking it.

Input

The first line contains three integers nk and p (1 ≤ n ≤ 1 000n ≤ k ≤ 2 0001 ≤ p ≤ 109) — the number of people, the number of keys and the office location.

The second line contains n distinct integers a1, a2, ..., an (1 ≤ ai ≤ 109) — positions in which people are located initially. The positions are given in arbitrary order.

The third line contains k distinct integers b1, b2, ..., bk (1 ≤ bj ≤ 109) — positions of the keys. The positions are given in arbitrary order.

Note that there can't be more than one person or more than one key in the same point. A person and a key can be located in the same point.

Output

Print the minimum time (in seconds) needed for all n to reach the office with keys.

Examples
input
2 4 5020 10060 10 40 80
output
50
input
1 2 101115 7
output
7
Note

In the first example the person located at point 20 should take the key located at point 40 and go with it to the office located at point 50. He spends 30 seconds. The person located at point 100 can take the key located at point 80 and go to the office with it. He spends 50seconds. Thus, after 50 seconds everybody is in office with keys.


题意:一共有n个人k把钥匙,每个人都需要先拿任意一把钥匙然后在去唯一的一个咖啡厅。问最少需要多少时间才能让所有人都进入咖啡厅。


二分 + 暴力:二分答案,通过暴力判断是否符合条件。在判断过程中如果左边的一个人去拿左边的某一把钥匙不符合条件,那么它右边的人去拿这把钥匙也必然不符合条件。时间复杂度O(n*m)。

下面是代码:

#include<iostream>#include<cstring>#include<cmath>#include<cstdio>#include<algorithm>#define MAX 2005#define INF 0x3f3f3f3f*2#define ll long longusing namespace std;int a[MAX],b[MAX];int n,m,p;bool Judge(int num){int k = 0;for(int j = 0; j < n; j++){bool ok = false;for(k; k < m; k++){//cout << k << ":" << abs(a[j] - b[k]) + abs(p - b[k]) << "/";if(abs(a[j] - b[k]) + abs(p - b[k]) <= num){k++;ok = true;break;}}//cout << endl;if(!ok) return false;}/*注意数据:2 2 1056 423 8 */return true;}int main( ){//cout << INF << endl;while(cin >> n >> m >> p){for(int j = 0; j < n; j++)cin >> a[j];for(int j = 0; j < m; j++)cin >> b[j];sort(a,a + n);sort(b,b + m);/*for(int j = 0; j < n; j++)cout << a[j] << " ";cout << endl;for(int j = 0; j < m; j++)cout << b[j] << " ";cout << endl;*/ll left = -1,right = INF,mid;/*left 起点必须是-1,hack数据:1 1 111 */while((right - left) > 1){mid = left + ((right - left)>>1);//cout << mid << endl; if(Judge(mid))right = mid;elseleft = mid;}cout << right << endl;}}
DP+贪心:DP[j][k]表示前j个人在前k个钥匙的范围内拿取钥匙,当计算到第k个钥匙时查看让第j个人拿会不会使得时间更优化。所以,动态转移方程式是:DP[j][k] = min(DP[j][k-1],max(abs(a[j] - b[k]) + abs(p - b[k]),DP[j - 1][k - 1]))。然后,在对于j 等于 k 的时间特殊处理一下就行了。时间复杂度O(n*m)。

下面是代码:

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#define MAX 2002#define ll long longusing namespace std;ll DP[MAX][MAX];int a[MAX],b[MAX];ll abs(ll a){return a > 0 ? a : -a;}ll max(ll a,ll b){return a > b ? a : b;}ll min(ll a,ll b){return a > b ? b : a;}int main( ){int n,m,p;while(cin >> n >> m >> p){for(int j = 1; j <= n; j++)cin >> a[j];for(int j = 1; j <= m; j++)cin >> b[j];sort(a + 1,a + 1 + n);sort(b + 1,b + 1 + m);/*for(int j = 1; j <= n; j++)cout << a[j] << " ";cout << endl;for(int j = 1; j <= m; j++)cout << b[j] << " ";cout << endl;*/for(int j = 1; j <= n; j++){DP[j][j] = max(DP[j - 1][j - 1],abs(a[j] - b[j]) + abs(p - b[j]));for(int k = j + 1; k <= m; k++)DP[j][k] = min(max(abs(a[j] - b[k]) + abs(p - b[k]),DP[j - 1][k - 1]),DP[j][k - 1]);}/*for(int j = 1; j <= n; j++){for(int k = 1; k <= m; k++)cout << DP[j][k] << " ";cout << endl; }*/cout << DP[n][m] << endl;}} 

        已经荒废了几个月了,本来就很菜,现在该重新捡起来了。继续给自己加油↖(^ω^)↗。






原创粉丝点击