本题属于带权二分图匹配问题,标准的解法是KM算法。但这里用两种更容易理解和记忆的算法:状态压缩DP,最短路径Dijsktra。本题的套路和1066.Campus bike II,1879.Minimum-XOR-Sum-of-Two-Arrays 差不多。
我们用m位二进制整数state表示学生被匹配的状态。比如0100101表示第1,4,6号学生与前三位导师进行了匹配。
我们令dp[j][state]表示前j个导师与学生匹配状态为state时,我们能得到的最大分数。注意,此时state显然应该恰好有j个bit 1. 状态转移的关键,就是考察当前的第j号导师匹配的是state里的哪一个学生?我们遍历state里比特为1的那些学生i,则有
dp[j][state] = max{dp[j-1][state - (1<<i)] + match[i][j] } for all i s.t. state[i]==1
事实上,从state里就可以得知我们有多少个导师被匹配了,所以dp下标里的第一个维度j可以省去,即
dp[state] = max{dp[state - (1<<i)] + match[i][j] } for all i s.t. state[i]==1
最终的答案是dp[(1<<m)-1]
.
本题乍看是求最大的分数,无法用最短路径和的Dijkstra算法。但是我们可以反过来考虑,令unmatch[i][j]表示导师i和学生j相匹配的话会丢失的分数。我们的目的是最小化导师和学生全部配对后的总丢失分数obj。最终输出的答案是m*n-obj
.
同样我们用state表示学生被匹配的状态。比如0100101表示第1,4,6号学生与前三位导师进行了匹配。它的邻接状态是:再选一个未曾匹配的学生与第四位导师进行匹配,比如(1)100101, 01(1)0101, 010(1)101等等都是可行的邻接节点(括号表示改动的位置)。
如果在state的基础上,我们再令第i位学生与第j位导师匹配得到新的状态state',那么这两个状态之间的路径就是unmatch[i][j]. 由此,我们把本题就转化为了状态节点之间的最短路径问题。起点的状态节点是000000,终点的状态节点是111111,我们希望求得起点到终点的最短路径。