本题属于带权二分图匹配问题,标准的解法是KM算法。这里只用状态压缩的搜索算法解决。思路和1066.Campus bike II
差不多。
我们用压缩状态state来代表nums1里有哪些元素已经匹配。比如01101表示nums1里面的第0,2,3号元素已经匹配。dp[state]表示当前该状态下能够得到的最优代价。注意到,dp[state]并不区分已经匹配的nums1元素究竟分别是和哪些nums2元素配对的。相比于暴力搜索我们需要穷举所有的配对细节,这样的“模糊处理”是节省时间和空间的关键。
我们依次遍历每个nums2的元素,考察nums2[j]加入后,能够如何更新dp[state]。举个例子,当考察j=2时,dp[state]表示使用了nums2的前3个(包括j=2)元素之后state的最优代价。那么state里面到底哪个nums1元素是与j相匹配呢?我们只要遍历state里面的bit 1即可,记那些bit 1对应的nums1的元素是i。于是就有转移方程dp[state] = dp[state-(1<<i)] + (nums1[i]^nums2[j])
.
最终的答案就是当nums1的所有元素都被匹配时的最优代价,即dp[(1<<m)-1]
.
在解法1的基础上可以有优化。根据题意,在考察nums2[j]的时候,说明我们已经匹配了nums2的前j+1个元素;因此相应地state必须恰好含有j+1个nums1的元素。所以我们不需要遍历所有的state,只需要遍历bit 1数目为j+1的state即可。这就可以用到Gospher's hack.
如果在状态A的基础上,我们再加上一对元素的配对,得到状态B,那么我们可以认为A到B之间有一条路径。比如,假设状态A是00101(nums1[0]和nums1[2]已经与nums2的前两个元素配对),在此基础上我们再将nums1[3]和nums2的第三个元素配对的话,就可以得到状态B是01101. 那么我们就认为A到B的路径的权重就是nums1[3]^nums2[2]
. 于是这道题就转化为了求从00000走到11111(nums1的所有元素都被配对)的最短距离。这就是Dijkstra算法。