Two City Scheduling

There are 2N people a company is planning to interview. The cost of flying the i-th person to city A is costs[i][0], and the cost of flying the i-th person to city B is costs[i][1].

Return the minimum cost to fly every person to a city such that exactly N people arrive in each city.

Example 1:

Input: [[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.

Note:

  1. 1 <= costs.length <= 100
  2. It is guaranteed that costs.length is even.
  3. 1 <= costs[i][0], costs[i][1] <= 1000

思路:这题用pq做,node代表的是去A不去B的benefit是多少,bcost - acost,按照benefit 从大到小sort,那么前N个元素去A,后面的去B;

class Solution {
    private class Node {
        public int benefit;
        public int acost;
        public int bcost;
        public Node(int benefit, int acost, int bcost) {
            this.benefit = benefit;
            this.acost = acost;
            this.bcost = bcost;
        }
    }
    
    public int twoCitySchedCost(int[][] costs) {
        PriorityQueue<Node> pq = new PriorityQueue<Node>((a, b) ->(b.benefit - a.benefit));
        for(int i = 0; i < costs.length; i++) {
            int acost = costs[i][0];
            int bcost = costs[i][1];
            int benefit = bcost - acost;
            pq.offer(new Node(benefit, acost, bcost));
        }
        
        int res = 0;
        int count = 0;
        while(!pq.isEmpty()) {
            Node node = pq.poll();
            if(count < costs.length / 2) {
                res += node.acost;
            } else {
                res += node.bcost;
            }
            count++;
        }
        return res;
    }
}

这题也可以用DP做;Top down, DFS + Memo cache; 这题就跟generate 左右括号那题一样;有n个人去A,有n个人去B,先写dfs的版本;然后加cache,写成dp的版本;

class Solution {
    public int twoCitySchedCost(int[][] costs) {
        int n = costs.length / 2;
        return dfs(costs, 0, n, n);
    }
    
    private int dfs(int[][] costs, int index, int aleft, int bleft) {
        if(index == costs.length) {
            return 0;
        }
        int acost = 0;
        if(aleft > 0) {
            acost = costs[index][0] + dfs(costs, index+1, aleft - 1, bleft);
        }
        int bcost = 0;
        if(bleft > 0) {
            bcost = costs[index][1] + dfs(costs, index+1, aleft, bleft - 1);
        }
        if(aleft > 0 && bleft > 0) {
            return Math.min(acost, bcost);
        } else if(aleft > 0) {
            return acost;
        } else {
            return bcost;
        }
    }
}

加上memo。 

class Solution {
    public int twoCitySchedCost(int[][] costs) {
        int n = costs.length / 2;
        int[][] memo = new int[n + 1][n + 1];
        return dfs(costs, 0, n, n, memo);
    }
    
    private int dfs(int[][] costs, int index, int aleft, int bleft, int[][] memo) {
        if(index == costs.length) {
            return 0;
        }
        if(memo[aleft][bleft] != 0) {
            return memo[aleft][bleft];
        }
        int acost = 0;
        if(aleft > 0) {
            acost = costs[index][0] + dfs(costs, index+1, aleft - 1, bleft, memo);
        }
        int bcost = 0;
        if(bleft > 0) {
            bcost = costs[index][1] + dfs(costs, index+1, aleft, bleft - 1, memo);
        }
        if(aleft > 0 && bleft > 0) {
            memo[aleft][bleft] = Math.min(acost, bcost);
        } else if(aleft > 0) {
            memo[aleft][bleft] = acost;
        } else {
            memo[aleft][bleft] = bcost;
        }
        return memo[aleft][bleft];
    }
}

 Buttom up, DP[i][j]代表的物理意义是:到目前为止第i + j个人,有i个人去A,有j个人去B的当前最小的cost;

dp[i][j] = Math.min(dp[i - 1][j] + costs[i + j - 1][0] // 第i + j个人去A

                                 dp[i][j - 1] + costs[i + j - 1][1] // 第i + j个人去B

初始化,1st row 就是没有人去A,全部是去B; dp[0][j] = dp[0][j - 1] + costs[j - 1][1];

初始化, 1st col 就是没有人去B, 全部是去A;  dp[i][0] = dp[i - 1][0] + costs[i - 1][0];

class Solution {
    public int twoCitySchedCost(int[][] costs) {
        int n = costs.length / 2;
        int[][] dp = new int[n + 1][n + 1];
        // init 1st row;
        for(int j = 1; j <= n; j++) {
            dp[0][j] = dp[0][j - 1] + costs[j - 1][1];
        }
        
        // init 1st col;
        for(int i = 1; i <= n; i++) {
            dp[i][0] = dp[i - 1][0] + costs[i - 1][0];
        }
        
        // calculate matrix;
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                dp[i][j] = Math.min(dp[i - 1][j] + costs[i + j - 1][0],
                                   dp[i][j - 1] + costs[i + j - 1][1]);
            }
        }
        return dp[n][n];
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值