LeetCode:返回将每个人都飞到某城市的最低费用

A company is planning to inerview 2n people.Given the array costs where 
costs[i]=[aCosti,bCosti],the cost of flying the ith person to city a is
aCosti,and the cost of flying the ith person to city b is bCosti.
Return the minimum cost of fly every person to a city such that exactly n people 
arrive in each city.

Example 1:
Input:costs=[[10,20],[30,200],[400,50],[30,20]]
Output:110
Explanation:
The first person goes to city A for a cost of 10.
The second person goes to city A for a cost of 30.
The third person goes to city B for a cost of 50.
The fourth person goes to city B for a cost of 20.
The total minimum cost is 10+30+50+20=110 to have half the people interviewing in each city.

Example 2:
Input:costs=[[259,770],[448,54],[926,667],[184,139],[840,118],[557,469]]
Output:1859
Explanation:
The total minimum cost is 259+54+667+184+118+557=1859 to have half the people interviewing 
in each city.

Example 3:
Input:costs=[[515,563],[451,713],[537,709],[343,819],[855,779],[457,60],[650,359],[631,42]]
Output:3086

题目大意:公司计划面试2n个人.第i人飞往A城市的费用是costs[i][0],飞往B城市的费用是costs[i][1],返回
将每个人都飞到某城市的最低费用,要求每个城市都有N个人抵达.

解题思路:
方法1:
写个递归算法,可惜超时.

方法2:
这道题关键点是在第i人在权衡A和B城市的两者之间的差值时达到最小,因此先利用map容器求出第i人的差值的绝对值,
根据multimap的降序排序,key值存储差值的绝对值,value存所在的index,枚举multimap,优先考虑差值大的,因为这
个影响着最低费用.最后分别考虑到达A和B城市的人数是否均为0.

方法3:
贪心算法
不用map,进行算法优化.
首先假设让所有人都去城市A,则总费用为去城市A的花费总和,考虑到需要一半的人去城市B,应该:若去城市B的花费小于城市
A的,则应该diff两者之间的差值,若去城市A的花费小于城市B的,则应该加上两者之间的差值.因此去城市B的减去去城市A的花费
,若为负数,则为diff,若为正数,则是追加的花费.当然希望是负数,而且越小越好.
整体的流程如下:
先假设都去A城市总费用ans,然后利用一个数组diff保存每个人的费用差值(去B城市的费用-去A城市的费用),然后对diff从小
到大进行排序,然后枚举diff数组前面一半部分+ans即为所求.

方法4:
官方做法,对于每个人的费用差:A城市的费用-B城市的费用,从小到到排序,然后枚举前半部分去A城市,后半部分去B城市

C++语言实现

#include <iostream>
#include <vector>
#include <map>
#include <cmath>
#include <algorithm>

using namespace std;
class Solution {
public:
    int twoCitySchedCost(vector<vector<int>>& costs) {
        int ans=0,k=0,A=costs.size()>>1,B=costs.size()>>1;
        multimap<int,int,greater<int>> board;//降序排序,multimap没有下标索引
        for(auto& cost:costs){
            board.insert(make_pair(abs(cost[0]-cost[1]),k++));
        }
        // for(auto b:board){
        //     cout<<b.first<<" "<<b.second<<endl;
        // }
        auto i=board.begin();
        while(i!=board.end()){
            if(A==0||B==0) break;
            if(costs[i->second][0]>costs[i->second][1]){
                B--;
                ans+=costs[i->second][1];
            }else{
                A--;
                ans+=costs[i->second][0];
            }
            i++;
        }
        //A不为0时
        for(;i!=board.end()&&A!=0;i++,A--){
            ans+=costs[i->second][0];
        }
        //B不为0时
        for(;i!=board.end()&&B!=0;i++,B--){
            ans+=costs[i->second][1];
        }
        return ans;
    }

    int twoCitySchedCostOne(vector<vector<int>>& costs) {
        int ans=0;
        vector<int> diff;
        for(auto& cost:costs){
            ans+=cost[0];
            diff.push_back(cost[1]-cost[0]);
        }
        sort(diff.begin(),diff.end(),less<int>());//从小到大排序,可以省略less
        for(int i=0;i<diff.size()/2;i++){
            ans+=diff[i];
        }
        return ans;
    }

    int twoCitySchedCostTwo(vector<vector<int>>& costs) {
        sort(costs.begin(),costs.end(),[&](vector<int>& A,vector<int>& B){
            return A[0]-A[1]<B[0]-B[1];
        });
        int ans=0,n=costs.size()>>1;
        for(int i=0;i<n;i++){
            ans+=costs[i][0]+costs[i+n][1];
        }
        return ans;
    }
};

int main(int argc,char* argv[]){
    vector<vector<int>> costs={{259,770},{448,54},{926,667},{184,139},{840,118},{577,469}};
    cout<<Solution().twoCitySchedCost(costs)<<endl;
    cout<<Solution().twoCitySchedCostOne(costs)<<endl;
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上的追梦人

您的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值