题目描述:
打车派单场景, 假定有N个订单, 待分配给N个司机。每个订单在匹配司机前,会对候选司机进行打分,打分的结果保存在N*N的矩阵A, 其中Aij 代表订单i司机j匹配的分值。
假定每个订单只能派给一位司机,司机只能分配到一个订单。求最终的派单结果,使得匹配的订单和司机的分值累加起来最大,并且所有订单得到分配。
输入描述:
第一行包含一个整数N,2≤N≤10。
第二行至第N+1行包含N*N的矩阵。
输出描述:
输出分值累加结果和匹配列表,结果四舍五入保留小数点后两位
(注意如果有多组派单方式得到的结果相同,则有限为编号小的司机分配编号小的订单,比如:司机1得到1号单,司机2得到2号单,
就比司机1得到2号单,司机2得到1号单要好)
示例1
输入
3
1.08 1.25 1.5
1.5 1.35 1.75
1.22 1.48 2.5
输出
5.25
1 2
2 1
3 3
说明
第一行代表得到的最大分值累加结果5.25,四舍五入保留两位小数;
第二行至第四行代表匹配的结果[i j],其中i按行递增:
订单1被派给司机2,订单2被派给司机1,订单3被派给司机3。使得A12+ A21+ A33= 1.25 + 1.5 + 2.5 = 5.25在所有的组合中最大。
算法思想:我们平时都是在一维的数组中用回溯法做题,但是这个回溯是在二维矩阵中选出满足条件的最优解。
为什么用回溯做这个题?
因为我们要选最优解,并且这些最优解伴随着选与不选的问题,还有选出来是否是最优的问题。是不是有点像全排列问题,一个数选过了就不能再选,只能在其它的数中选择。
题目的要求:
我们只需要选择每一个(i,j),其中i不重复,j不重复,使得他们加起来的值全局最大。也就是每一行选一个数,每一列选一个数,进行 组合起来,使得全部的n(i,j)的值加起来最大。
代码实现:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
void backTrack(vector<vector<double>>& num,vector<bool>&used, vector<int>& pre,
vector<int>& cur,double curProfit, double&preProfit, int n, int pos)
{
if (pos == n) //如果pos == n 说明行数已经达到n行,所有的都已经选完
{
if (curProfit > preProfit) //全局找最大
{
preProfit = curProfit;
pre = cur; //数组赋值,将这个最优解的数组赋值给pre
}
return;
}
for (int i = 0; i < n; i++)
{
if (!used[i]) // 标记第 i列,下一次第i列就不能选择了
{
cur[pos] = i; // 记录每一个 pos行对应的列数i 下面的就是回溯过程
curProfit += num[pos][i];
used[i] = true;
backTrack(num,used,pre,cur, curProfit, preProfit, n, pos + 1);
curProfit -= num[pos][i];
used[i] = false;
}
}
}
int main()
{
int n;
while (cin >> n)
{
vector<vector<double>> vvd(n, vector<double>(n));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> vvd[i][j];
}
}
vector<int> pre(n); // 记录最优解的每个值 所在的 列数
vector<int> cur(n); // 列数加入数组
vector<bool> used(n); // 标记数组, 因为一列只能选择一个
double preProfit = INT_MIN; // 全局的最大值
double curProfit = 0.0; // 当前的最大值
int pos = 0; // pos就是行数,pos到达一行,就选y值就可以了
backTrack(vvd, used, pre, cur, curProfit, preProfit, n, pos);
cout << preProfit << endl;
for (int i = 0; i < pre.size(); i++)
{
cout << i + 1 << " " << pre[i] + 1 << endl;
}
}
}
牛客网题目链接:https://www.nowcoder.com/questionTerminal/3f495307bfca40e49b0e2b15b14ce923