运动员最佳配对问题

来源:互联网 发布:淘宝卖家群 编辑:程序博客网 时间:2024/05/17 02:02

西安交大 软件53 蔡少斐

题号:6_5

题目叙述:

羽毛球队有男女运动员各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]。

 

设计一个算法,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。

 

编程任务:设计一个算法,对于给定的男女运动员竞赛优势,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。

输入格式

输入数据第一行有1 个正整数n (1≤n≤10)。接下来的2n行,每行n个数。前n行是P,后n行是Q。

 

输出格式

将计算出的男女双方竞赛优势的总和的最大值输出。

输入样例


10 2 3 
2 3 4 
3 4 5 
2 2 2 
3 5 3 
4 5 1 

输出样例

52 

题目解答:

       这道题目共有n!种配对情况,也就是相当于固定男运动员,然后对女运动员进行一次全排列,并求出对应的优势之和的最大值,本题可以用回溯法,也可以用分支限界法,在使用分支限界法的时候,关键是在于设计上界函数。

       在这里,我们把上界函数定义为:剩下的未配对的女运动员(不考虑男运动员配对情况下)所能达到的优势最大值之和(记为r)与当前配对已达到的优势(记为sum)之和。在程序里体现如下:


在一开始时候,r被初始化为:


其中maxout的定义为:


       在使用分支限界法的时候,一旦有一个叶节点出来,那么就立即结束算法,因为最先出来的叶节点必定是最优解。

代码实现:

#include<algorithm>#include<iostream>#include<queue>#include<vector>#include <cstdio>usingnamespace std;const int MAX = 20;int          P[MAX][MAX];int          Q[MAX][MAX];int          maxout[MAX];int          n;structnode {       int   id;       int   sum;       int   r;       int   up;       int   *x;};structcmp {       bool operator()( node* a, node* b )       {              return(a->up < b->up);       }};voidsolve(){       int                                      ans= 0;       priority_queue<node*,vector<node*>, cmp>  que;       node                                         *E = new node();       E->id      =1;       E->sum  =0;       E->r       =0;       E->up    =0;       for ( int i = 1; i <= n; i++ )       {              E->r += maxout[i];       }       E->up    =E->r;       E->x       =new int[n + 1];       for ( int i = 1; i <= n; i++ )       {              E->x[i] = i;       }       while ( E->id != n + 1 )       {              for ( int i = E->id; i <= n;i++ )              {                     node* nE = new node();                     nE->id    = E->id + 1;                     nE->x     = new int[n + 1];                     for ( int t = 1; t <= n;t++ )                     {                            nE->x[t] =E->x[t];                     }                     nE->x[E->id] = E->x[i];                     nE->x[i]  = E->x[E->id];                     nE->sum              = E->sum +P[E->id][nE->x[E->id]] * Q[nE->x[E->id]][E->id];                     nE->r            = E->r - maxout[E->id];                     nE->up         = nE->sum + nE->r;                     que.push( nE );              }              if ( !que.empty() )              {                     E= que.top();                     que.pop();              }else  {                     ans = 0;                     break;              }       }       ans = E->sum;       cout << ans << endl;}  intmain(){       cin >> n;       for ( int i = 1; i <= n; i++ )       {              for ( int j = 1; j <= n; j++ )              {                     cin >> P[i][j];              }       }       for ( int i = 1; i <= n; i++ )       {              for ( int j = 1; j <= n; j++ )              {                     cin >> Q[i][j];              }       }       for ( int i = 1; i <= n; i++ )       {              int ma = 0;              for ( int j = 1; j <= n; j++ )              {                     ma = max( ma, Q[i][j] *P[j][i] );              }              maxout[i] = ma;       }       solve();       return(0);}  /* * 3 * 10 2 3 * 2 3 4 * 3 4 5 * 2 2 2 * 3 5 3 * 4 5 1 */


运行结果: