Codeforces 830A. Office Keys (背包dp+貪心) / (二分+貪心)
阿新 • • 發佈:2017-07-14
d+ 背包dp 表示 cnblogs name return set office sed
題目鏈接:
http://codeforces.com/problemset/problem/830/A
題意:
n個人,k個鑰匙(n<=k),p表示這些人要到達的位置
給出n個人的位置以及鑰匙的位置,問花時間最多的那個人用時最少是多少??
思路:
二分+貪心: 二分最少時間,需要對a,b位置數組排序,我們check函數只需要從左到右一個一個找過去,因為如果選後邊的點,可能會使結果更差,假如當前這個人選後面的點,那可能會選中後面的人可以選的唯一的鑰匙,不會使解更優。
check(40)的時候答案是false,是錯誤的,因為第一個人把第二個人可以唯一選的鑰匙選上了。
復雜度是 O((n+k)*log(2e9))
dp+貪心:
dp[i][j]表示前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))); dp[i][j-1]: 表示不選第 j 把鑰匙 max(dp[i-1][j-1],abs(a[i]-b[j])+abs(b[j]-p)): 表示選第 j 把鑰匙,就是考慮前 i-1 個人用前 j-1 把鑰匙,第i個人用第j把鑰匙,取最長的時間,因為答案要最長的人的時間 顯然 取二者最小就是答案了 ----》 背包?dp真奇妙啊!
代碼一:
#include <bits/stdc++.h> usingnamespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 2e3+10; ll dp[maxn][maxn],a[maxn],b[maxn]; int main(){ int n,k,p; cin >> n >> k >> p; for(int i=1; i<=n; i++) cin >> a[i]; for(int i=1; i<=k; i++) cin >> b[i]; sort(a+1,a+1+n); sort(b+1,b+1+k); for(int i=0; i<=n; i++) for(int j=0; j<=k; j++) dp[i][j] = INFLL; for(int i=0; i<=k; i++) dp[0][i]=0; for(int i=1; i<=n; i++) for(int j=i; j<=k; j++){ dp[i][j] = min(dp[i][j-1],max(dp[i-1][j-1],abs(a[i]-b[j])+abs(b[j]-p))); } cout << dp[n][k] << endl; return 0; }
代碼二:
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 2e3+10; int n,k,pos; ll a[maxn],b[maxn]; bool used[maxn]; bool check(ll x){ int p = 0; for(int i=1; i<=n; i++){ while(p<=k){ p++; if(1LL*(abs(a[i]-b[p])+abs(b[p]-pos))<=x) break; } if(p > k) return false; } return true; } int main(){ cin >> n >> k >> pos; for(int i=1; i<=n; i++) a[i] = read(); for(int i=1; i<=k; i++) b[i] = read(); sort(a+1,a+n+1); sort(b+1,b+k+1); ll L=0,R=2e9,ans=INFLL; while(L<=R){ ll mid = (L+R)/2; if(check(mid)) ans=mid,R=mid-1; else L = mid+1; } cout << ans << endl; return 0; }
Codeforces 830A. Office Keys (背包dp+貪心) / (二分+貪心)