LeetCode解题分享:1029. Two City Scheduling

Problem

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
解题思路

   题目很简单,但是却不是那么容易求解的。此处我们可以使用动态规划的方法求解,可以看出,定义一个一维的数组来求解问题是不合适的,因为状态是由两个变量组成的,一个是当前的总人数,另一个数在这些人中有多少人去了A城市。所以很显然,我们的状态转移数组应该定义成一个二维数组。

   我们定义一个二维数组 d p [ i ] [ j ] dp[i][j] dp[i][j],每一行表示前面的 i i i个人中,有 j j j个人去了A城市的花费的最小值,假设一共有m个人需要安排(m是个偶数),那么我们的数组大小就应该是 [ m + 1 , m 2 + 1 ] [m + 1, \frac{m}{2} + 1] [m+1,2m+1],这里的1表示的是多余的0。那么接下来就是看状态转移的情况。假设我们考虑第 i i i个人的情况,如果这个人要去A城市,那么,列数是需要加1的,也就是说去A城市的人数要加1,那么,有 d p [ i − 1 ] [ j − 1 ] + c o s t s [ A ] = d p [ i ] [ j ] dp[i - 1][j - 1] + costs[A] = dp[i][j] dp[i1][j1]+costs[A]=dp[i][j]。如果这个人要去B城市,那么列数是不变的,也就是说去A城市的人的数目是不变的,那么有 d p [ i − 1 ] [ j ] + c o s t s [ B ] = d p [ i ] [ j ] dp[i - 1][j] + costs[B] = dp[i][j] dp[i1][j]+costs[B]=dp[i][j]。所以很明显,我们取二者之间的最小值即可,这样的两重循环,一直到返回最后的一个数据,然后返回 d p [ m ] [ m 2 ] dp[m][\frac{m}{2}] dp[m][2m]即可。

   需要注意的是第0行和第0列的初始化情况。第0行一般初始化为一个很大的数,第0列则是costs中去B城市花费的累加和。

   代码如下:

class Solution:
    def twoCitySchedCost(self, costs):
        N = len(costs)
        dp = [[float('inf') for i in range(N // 2 + 1)] for j in range(N + 1)]

        cnt = 0
        for i in range(len(dp)):
            dp[i][0] = cnt
            if i < len(costs):
                cnt += costs[i][1]

        for i in range(1, len(dp)):
            for j in range(1, min(N // 2, i) + 1):
                # print(i, " ", j)
                t1 = dp[i - 1][j - 1] + costs[i - 1][0]
                t2 = dp[i - 1][j] + costs[i - 1][1]
                dp[i][j] = min(dp[i][j], t1, t2)

        return dp[-1][-1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值