A. Office Keys(二分+思维贪心含证明)
发布日期:2021-06-30 10:18:00 浏览次数:2 分类:技术文章

本文共 2301 字,大约阅读时间需要 7 分钟。

本来都想到二分开始写check函数的,结果脑子一乱觉得不能贪心…

贪心法则

对 于 二 分 的 时 间 x , 最 左 边 的 人 要 尽 量 选 最 左 边 的 钥 匙 \color{Red}对于二分的时间x,最左边的人要尽量选最左边的钥匙 x,

当 最 左 边 的 钥 匙 在 最 左 边 人 的 左 边 时 显 然 正 确 , 因 为 后 面 的 人 想 拿 这 把 要 走 回 来 , 要 走 更 多 的 路 当最左边的钥匙在最左边人的左边时显然正确,因为后面的人想拿这把要走回来,要走更多的路 ,,

当 最 左 边 的 钥 匙 在 最 左 边 人 的 右 边 时 , 需 要 想 一 想 , 我 就 是 这 里 没 想 通 。 当最左边的钥匙在最左边人的右边时,需要想一想,我就是这里没想通。 ,,

也许你会说,这个时候去拿右边的钥匙会不会更优?

你 要 这 么 想 , 你 能 拿 到 右 边 的 钥 匙 , 那 么 右 边 的 人 肯 定 也 能 拿 到 这 把 钥 匙 你要这么想,你能拿到右边的钥匙,那么右边的人肯定也能拿到这把钥匙 ,,

但 是 你 要 是 拿 左 边 一 点 , 后 面 的 人 但是你要是拿左边一点,后面的人 ,可能 就 拿 不 到 这 把 钥 匙 , 因 为 后 面 的 人 需 要 走 回 来 就拿不到这把钥匙,因为后面的人需要走回来 ,

#include 
using namespace std;const int maxn=2e5+10; #define int long longint n,k,p,ans,vis[maxn],a[maxn],b[maxn];bool isok(int s){ int index=1; for(int i=1;i<=n;i++) { while( abs(a[i]-b[index])+abs(p-b[index]) > s) { index++; if(index>k) return false; } index++; } return true;}signed main(){ 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); int l=0,r=2e9,mid; while(r>=l) { mid = (l+r)>>1; if( isok(mid) ) r=mid-1,ans=mid; else l=mid+1; } cout<

还 有 d p 的 , 但 实 际 上 也 是 基 于 上 面 的 结 论 , 左 边 的 人 用 左 边 的 还有dp的,但实际上也是基于上面的结论,左边的人用左边的 dp,,

设 d p [ i ] [ j ] 为 前 i 个 人 用 前 j 把 钥 匙 设dp[i][j]为前i个人用前j把钥匙 dp[i][j]ij

那 么 每 次 可 以 d p [ i ] [ j ] = d p [ i ] [ j − 1 ] , 不 使 用 第 j 把 钥 匙 那么每次可以dp[i][j]=dp[i][j-1],不使用第j把钥匙 dp[i][j]=dp[i][j1],使j

用 第 j 把 钥 匙 , d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j − 1 ] , a b s ( a [ i ] − b [ j ] ) + a b s ( p − b [ j ] ) ) 用第j把钥匙,dp[i][j]=max(dp[i-1][j-1],abs(a[i]-b[j])+abs(p-b[j])) j,dp[i][j]=max(dp[i1][j1],abs(a[i]b[j])+abs(pb[j]))

#include 
using namespace std;typedef long long ll;const int maxn=2009;ll dp[maxn][maxn],a[maxn],b[maxn],n,k,p;int main(){ 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); memset(dp,20,sizeof(dp)); for(int j=0;j<=k;j++) dp[0][j]=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(p-b[j])) ); cout<

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/107216571 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:C. Minimal string(贪心法,栈)
下一篇:A. String Reconstruction(三种解法,排序贪心或跳步或并查集)

发表评论

最新留言

很好
[***.229.124.182]2024年04月25日 10时11分31秒