美团--订单分配
美團(tuán)–訂單分配
文章目錄
- 美團(tuán)--訂單分配
- 一、題目描述
- 二、分析
- 三、代碼
一、題目描述
打車派單場(chǎng)景, 假定有N個(gè)訂單, 待分配給N個(gè)司機(jī)。每個(gè)訂單在匹配司機(jī)前,會(huì)對(duì)候選司機(jī)進(jìn)行打分,打分的結(jié)果保存在N*N的矩陣A, 其中A[i][j] 代表訂單i司機(jī)j匹配的分值。
假定 每個(gè)訂單只能派給一位司機(jī),司機(jī)只能分配到一個(gè)訂單。求最終的派單結(jié)果,使得匹配的訂單和司機(jī)的分值累加起來最大,并且所有訂單得到分配。
- 輸入描述:
- 輸出描述:
二、分析
- 注意題中的一個(gè)條件“每個(gè)訂單只能派給一位司機(jī),司機(jī)只能分配到一個(gè)訂單”,因?yàn)镹*N的矩陣A中保存著每個(gè)顧客對(duì)司機(jī)的打分情況,而A[i][j] 代表訂單i司機(jī)j匹配的分值。
- 這就意味著我們?cè)贏數(shù)組中進(jìn)行選擇的時(shí)候每一行每一列只能選擇一個(gè)
- 那么這個(gè)問題就和n皇后問題、全排列問題基本上是一致的了,是一個(gè)典型的回溯算法的思路,求所有排列當(dāng)中結(jié)果最大的一種情況
- 直接看代碼:
三、代碼
#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) {//如果pos == n 說明行數(shù)已經(jīng)達(dá)到n行,所有的行都已經(jīng)選完,是一種結(jié)果if (pos == n) {//全局找最大,判斷是否出現(xiàn)更優(yōu)解if (curProfit > preProfit) {//更新當(dāng)前最大的和preProfit = curProfit;//數(shù)組賦值,將這個(gè)最優(yōu)解的數(shù)組賦值給pre,最后用來輸出pre = cur; }return;}//枚舉第pos行的每一列for (int i = 0; i < n; i++){//改行必須在之前沒有被選擇使用過,必須滿足題意if (!used[i]) // 標(biāo)記第 i列,下一次第i列就不能選擇了{//代表本次選擇pos行的i列元素,進(jìn)行標(biāo)記本次遞歸的選擇位置//因?yàn)榭赡艹霈F(xiàn)本次選擇是最優(yōu)的情況,所以需要保存cur[pos] = i; // 記錄每一個(gè) pos行對(duì)應(yīng)的列數(shù)i,下面的就是回溯過程//代表當(dāng)前的評(píng)分和加上本次的選擇//同理和cur一樣都要保存curProfit += num[pos][i];//代表著第i例被使用過,下次不能在選擇第i列used[i] = true;backTrack(num,used,pre,cur, curProfit, preProfit, n, pos + 1);//撤銷選擇curProfit -= num[pos][i];//撤銷標(biāo)記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); // 記錄最優(yōu)解的每個(gè)值 所在的 列數(shù)vector<int> cur(n); // 列數(shù)加入數(shù)組vector<bool> used(n); // 標(biāo)記數(shù)組, 因?yàn)橐涣兄荒苓x擇一個(gè)double preProfit = INT_MIN; // 全局的最大值double curProfit = 0.0; // 當(dāng)前的最大值int pos = 0; // pos就是行數(shù),pos到達(dá)一行,就選y值就可以了backTrack(vvd, used, pre, cur, curProfit, preProfit, n, pos); //打印結(jié)果printf("%4.2f\n",preProfit);//cout << preProfit << endl;for (int i = 0; i < pre.size(); i++){cout << i + 1 << " " << pre[i] + 1 << endl;}} }總結(jié)
- 上一篇: 力扣--扁平化嵌套列表迭代器
- 下一篇: 美团--美团骑手包裹区间分组