Codeforces 830A. Office Keys (背包dp+贪心) / (二分+贪心)
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 830A. Office Keys (背包dp+贪心) / (二分+贪心)相关的知识,希望对你有一定的参考价值。
题目链接:
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> 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; 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+贪心) / (二分+贪心)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 830D Singer House - 动态规划
Codeforces 830D Singer House 动态规划