1、问题描述:羽毛球队有男女运动员个n人。给定2个n*n矩阵P和Q。P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势;Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势。由于技术配合和心理状态等各种因素影响,P[i][j]不一定等于Q[j][i]。男运动员i和女运动员j配对组成混合双打的男女双方竞赛优势为P[i][j]*Q[j][i]。设计一个算法,计算男女运动员最佳配对法,使个组男女双方竞赛优势的总和达到最大。
2、算法设计:设计一个算法,对于给定的男女运动员竞赛优势,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。
3、数据输入:有文件input.txt给出输入数据。第一行有1个正整数n(1<=n<=20)。接下来的2n行,每行n个数。前n行是p,后n行是q。
4、结果输出: 将计算的男女双方竞赛优势的总和的最大值输出到文件output.txt。
输入文件示例 输出文件示例
Input.txt output.txt
3 52
10 2 3
2 3 4
3 4 5
2 2 2
3 5 3
4 5 1
二、解题思路
因为此问题的解空间是一棵排列树,所以可以直接套用搜索排列树回溯算法框架,首先创建P,Q全局变量,记录配对的局部竞争优势,Re记录配对情况,然后构造一个类,使用排列树框架的回溯算法实现配对问题
三、算法描述
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
using namespace std;
vector<int> Re; //全局变量,Re用来记录配对情况
vector<vector<int>> P;
vector<vector<int>> Q;
class Assign
{
friend int PairUp(int);
private:
bool Place(int k);
void Backtrack(int k);
int n;
int sum;
vector<int> x;
public:
Assign(int m,int c,int b)
{
x.resize(m+1);
Re.resize(m+1);
n = c;
sum = b;
}
~Assign() { }
};
bool Assign::Place(int k)
{
for(int j=1;j<k;j++)
if(x[j]==x[k]) //不同男运动员和同一个女运动员配对
return false;
return true;
}
void Assign::Backtrack(int t)
{
if(t>n)
{
int temp=0; //第次还原为进行下次的累加
for(int i=1;i<=n;i++)
{
temp += (P[i][x[i]]) * (Q[x[i]][i]); //累加,得到一个可行解
}
if(sum<=temp) //记录最大可行解
{
sum=temp;
copy(x.begin(),x.end(),Re.begin());
}
}
else
for(int i=t;i<=n;i++)
{
swap(x[t],x[i]);
if(Place(t))
Backtrack(t+1);
swap(x[t],x[i]);
}
}
int PairUp(int n)
{
Assign X(n,n,0);
vector<int> p;
for(int i=0;i<=n;i++)
p.push_back(i);
copy(p.begin(),p.end(),X.x.begin());
X.Backtrack(1);
return X.sum;
}
int main()
{
ifstream fin("input.txt");
ofstream fout("output.txt");
int n,i,j,temp;
vector<int> r;
vector<int> t;
fin>>n;
r.push_back(0);
P.push_back(r);
t.push_back(0);
Q.push_back(t);
cout<<"从文件input.txt中获得数据...."<<endl;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{ fin>>temp;r.push_back(temp);}
P.push_back(r);
for(vector<int>::iterator vr = r.begin()+1;vr != r.end();)
{ vr = r.erase(vr);}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{ fin>>temp;t.push_back(temp);}
Q.push_back(t);
for(vector<int>::iterator vt = t.begin()+1;vt != t.end();)
{ vt = t.erase(vt);}
}
cout<<"结果为:"<<PairUp(n)<<",并已保存至output.txt..."<<endl<<endl;
cout<<"男运动员"<<" & "<<"女运动员"<<endl;
for(i=1;i<=n;i++)
{
cout<<setw(4)<<i<<setw(12)<<Re[i]<<endl;
}
fout<<PairUp(n)<<endl;
return 0;
}