Algorithm 如何求M的最小值?

Algorithm 如何求M的最小值?,algorithm,Algorithm,我试图解决这个问题: 你有N个亲戚。您将与ith relative进行详细交谈 分钟。每分钟花你1美元。谈话结束后,, 他们会在你的手机里加上席币。最初,你 在你的手机里有M美元的余额 求出M的最小值,这是您在 电话,这样你就不会在任何通话中失去平衡 (遇到负平衡) 注意:你可以按任何顺序给亲戚打电话。每个亲戚都会 只打过一次电话 输入: N T1 X1 T2 X2 2 1 1 2 1 2 输出: N T1 X1 T2 X2 2 1 1 2 1 2 起初我觉得这很容易,但

我试图解决这个问题:

你有N个亲戚。您将与ith relative进行详细交谈 分钟。每分钟花你1美元。谈话结束后,, 他们会在你的手机里加上席币。最初,你 在你的手机里有M美元的余额

求出M的最小值,这是您在 电话,这样你就不会在任何通话中失去平衡 (遇到负平衡)

注意:你可以按任何顺序给亲戚打电话。每个亲戚都会 只打过一次电话

输入:

N
T1  X1
T2  X2

2
1 1 
2 1
2
输出:

N
T1  X1
T2  X2

2
1 1 
2 1
2
起初我觉得这很容易,但我找不到确切的解决方案

我最初的想法:

N
T1  X1
T2  X2

2
1 1 
2 1
2
我们在
Xi>Ti
的地方没有问题,因为这不会减少我们的初始成本 平衡。我们需要注意我们将要去的地方 损失,即
Ti>Xi
。 但我无法表达,这将导致最低限度的 初始值


在处理此问题时需要指导以找到最佳解决方案。

更新:-

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100007

int n,diff;
vector<pair<int,int> > v1,v2;

int main(){
    diff = 0;
    cin>>n;
    for(int i=0;i<n;i++){
    int cost,recharge;
    cin>>cost>>recharge;
    if(recharge > cost){
       v1.push_back(make_pair(cost,recharge));
    }else{
       v2.push_back(make_pair(recharge,cost));
    }
    diff += (cost-recharge);
   }
   sort(v1.begin(), v1.end());
   sort(v2.begin(), v2.end());
   if(v2.size() > 0)diff += v2[0].first;
   int max_req = diff, req = 0,cur = 0;
   for(int i=0; i<v1.size(); i++){
      req = v1[i].first - cur;
      max_req = max(max_req, req);
      cur += v1[i].second-v1[i].first;
   }
   cout<<max(max_req,diff)<<endl;
   return 0;
}
二进制搜索方法似乎会导致错误的结果(如 用户在下面的注释中提供了测试用例

所以,这是另一种方法。我们保持通话成本之间的差异 和充值金额

然后我们维护两个数组/向量。 如果我们的充值金额严格大于通话成本,我们将 调用在第一个数组中,否则我们把它放在第二个数组中

然后我们可以根据成本对第一个数组和第二个数组进行排序 根据充值金额。然后通过添加 通话费用大于充值的最低充值金额

然后我们可以遍历第一个数组并更新最大值 需求,每次通话的需求和当前余额。最后,我们的答案 将是最大需求和我们保持的差异之间的最大值

示例:-

   N = 2
   T1 = 1 R1 = 1
   T2 = 2 R2 = 1
我们的第一个数组不包含任何内容,因为所有调用的开销都大于 或者等于充值金额。因此,我们将两个呼叫都放在第二个数组中 在我们对数组进行排序之前,diff被更新为2 充电我们可以从通话中获得我们的差异(即1)。现在,差异站起来了 那么,由于我们的第一个数组不包含任何元素,我们的答案等于 差异即3

时间复杂度:-O(nlogn)

工作示例:-

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100007

int n,diff;
vector<pair<int,int> > v1,v2;

int main(){
    diff = 0;
    cin>>n;
    for(int i=0;i<n;i++){
    int cost,recharge;
    cin>>cost>>recharge;
    if(recharge > cost){
       v1.push_back(make_pair(cost,recharge));
    }else{
       v2.push_back(make_pair(recharge,cost));
    }
    diff += (cost-recharge);
   }
   sort(v1.begin(), v1.end());
   sort(v2.begin(), v2.end());
   if(v2.size() > 0)diff += v2[0].first;
   int max_req = diff, req = 0,cur = 0;
   for(int i=0; i<v1.size(); i++){
      req = v1[i].first - cur;
      max_req = max(max_req, req);
      cur += v1[i].second-v1[i].first;
   }
   cout<<max(max_req,diff)<<endl;
   return 0;
}
#包括
使用名称空间std;
#定义MAXN 100007
int n,diff;
向量v1,v2;
int main(){
差异=0;
cin>>n;
对于(int i=0;i>成本>>充值;
如果(充值>成本){
v1.推后(制作配对(成本、充电));
}否则{
v2.推回(使配对(充电、成本));
}
差异+=(成本再收费);
}
排序(v1.begin(),v1.end());
排序(v2.begin(),v2.end());
如果(v2.size()>0)diff+=v2[0],则为第一;
int max_req=diff,req=0,cur=0;
对于(int i=0;i(这是一篇维基帖子:你被邀请编辑,不需要太多的声誉就可以编辑,不需要版主参与。)
高效工作意味着不费吹灰之力地完成手头的任务。以下方面:

  • 在处理此问题以找到最佳解决方案时,要求提供
    指导
    ——而不是解决方案(这样做)
  • 问题陈述要求
    M的最小值
    ——不是最佳的调用顺序或如何找到它
为了找到最初需要的最小余额,对亲属/(T,X)-对/呼叫进行分类(如果不是针对所述问题,则顺序可能有意义)

  • T 开始假设初始余额为1。对于每个通话,如果你能负担得起,减去其成本,加上退款,并对其进行会计处理。如果你还负担不起,将其搁置/搁置/在优先队列中。在“奖励通话”结束时,依次移除队列中的每个队列头,以考虑初始余额的必要增加。
    这一部分以迄今为止最高的平衡结束
  • T=X 对任何其他通话都没有影响。只需按任何顺序在最高余额处执行即可。
    整个序列所需的最高余额不能低于任何单个调用的成本,包括这些调用
  • T>X 在后续通话中减少T-X。按减少退款的顺序执行。
    (这可能与任何催缴股款一样,在退款前余额为零。 由于通话顺序不会改变总成本,因此需要最少初始余额的通话将是产生最低最终余额的通话。对于此类通话需要的中间余额,请不要忘记最低退款。)
  • 将所有类别的要求结合起来。

    请记住指导请求。

    请提供拒绝投票的原因。如果没有提供任何拒绝投票的原因,请不要拒绝投票。没有拒绝投票,但问题应该是独立的。您需要在线程中提供问题,而不仅仅是通过链接。此外,您没有显示您尝试过的内容。而且,链接不可用没有注册的标签,所以大多数读者无论如何都看不到这个问题。好的。我会编辑它…我以为这个问题会出现。谢谢。重新思考第一个想法:如果你从一美元开始,不谈2分钟远一个退款3?(我怀疑这是一个封闭的表达。)你的解决方案看起来很有希望。但这不是O(nlogn)解决方案。当仍有调用时,如何检查它是否永远不会达到0?线性??如果您能用一个小示例演示您的算法,这将是一件好事。Thanks@user2125722谢谢。你也添加了代码:)但我要求演示。用一个例子。任何一个小例子来展示你的代码是如何工作的。谢谢。到目前为止你帮了我的忙,只做了最后一次更新。我看到了一个昂贵的,如果有的话