算法入门10

一、 羽毛球队有男女运动员各 n n n人。给定2 个 n × n n×n n×n 矩阵 P P P Q Q Q P [ i ] [ j ] P[i][j] P[i][j] 是男运动员 i i i 和女运动员 j j j 配对组成混合双打的男运动员竞赛优势; Q [ i ] [ j ] Q[i][j] Q[i][j] 是女运动员 i i i 和男运动员 j j j 配合的女运动员竞赛优势。由于技术配合和心理状态等各种因素影响, P [ i ] [ j ] P[i][j] P[i][j]不一定等于 Q [ j ] [ i ] Q[j][i] Q[j][i]。男运动员 i i i 和女运动员 j j j 配对组成混合双打的男女双方竞赛优势为 P [ i ] [ j ] × Q [ j ] [ i ] P[i][j]\times Q[j][i] P[i][j]×Q[j][i]。设计一个算法,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。

  • 选用回溯法进行求解。

    ​ 首先将 n n n 个男运动员和 n n n 个女运动员分别从小到大编号为 1 ∼ n 1\sim n 1n ,之后将 n n n 个男运动员的位置确定,对 n n n 个女运动员进行全排列,可以用构建排列树的方法求解。求解结果应为:
    max ⁡ ∑ i = 1 n ∑ j = 1 n P [ i ] [ j ] × Q [ j ] [ i ] \max \sum_{i=1}^{n} \sum_{j=1}^{n} P[i][j]\times Q[j][i] maxi=1nj=1nP[i][j]×Q[j][i]
    解空间: n = 4 n=4 n=4 为例,构建出的排列树的解空间如下图所示(仅给出了排列中第一个女生为编号1时的部分,边上的值表示为排列的女生编号):

1
2
3
4
3
4
2
4
2
3
4
3
4
2
3
2
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q

可行性约束条件:

限界函数: 设置宽松限界条件:若前 k k k 个小组与剩余的任意组合的最大竞争优势相加之和 比 当前已找到的最大竞争优势还小,那该方案必不满足,可以进行剪枝。

​ 对于 n n n 个男运动员,先求得其与女运动员排列的最大值,即求 P P P 矩阵每一行中的最大值进行相加,得到 r r r ,每次减去当前的最大值。即:
r = ∑ i = k + 1 n max ⁡ 1 ≤ m ≤ n ( P [ i ] [ m ] × Q [ m ] [ i ] ) r=\sum_{i=k+1}^n \max_{1\leq m\leq n} (P[i][m]\times Q[m][i]) r=i=k+1n1mnmax(P[i][m]×Q[m][i])
​ 故该限界函数为:
∑ i = 1 k P [ i ] [ j ] × Q [ j ] [ i ] + ∑ i = k + 1 n max ⁡ 1 ≤ m ≤ n ( P [ i ] [ m ] × Q [ m ] [ i ] ) > m a x f \sum_{i=1}^k P[i][j]\times Q[j][i] +\sum_{i=k+1}^n \max_{1\leq m\leq n} (P[i][m]\times Q[m][i])> maxf i=1kP[i][j]×Q[j][i]+i=k+1n1mnmax(P[i][m]×Q[m][i])>maxf
构建好树之后,求解过程的算法描述如下:

public class Athe{
    static int n;  //男女运动员配对组数
    static int f;  //当前计算下竞赛优势的总和
    static int r;  //当前剩余组合的最大竞争优势
    static int maxf;  //当前最大值
    static int [][]p;  //男运动员竞赛优势
    static int [][]q;  //女运动员竞赛优势
    static int []max_line;  //二元数组p中每一行中的最大值
    static int []x;  //当前的排列顺序
    static int []maxx;  //当前最优的排列顺序
    
    private static void maxLine(int x)  //求每一行中的最大值
    {
        int thismax=0;
        for (int i=0; i<n; i++){
            for (int j=0; j<n; j++){
                if(thismax < p[i][j])
                    thismax=p[i][j]
            }
            max_line[i]=thismax;
        }
    }
    
    public static void cal_r()  //计算初始r值
    {
        for (int i=0; i<n; i++){
            r += max_line[i];
        }
    }
    
    private static void backtrack(int i)
    {
        if(i>n){  //到达叶子结点,搜索到最底部
            for(int j=1; j<=n; j++) maxx[j]=x[j];
            maxf=f;
        }
        else{  //非叶子结点
            for(int j=i; j<=n; j++){
                f += P[i][x[j]]*Q[x[j]][i];
                r -= max_line[i];
                if(f+r > maxf){  //限界条件
                    MyMath.swap(x,i,j);
                    backtrack(i+1);
                    MyMath.swap(x,i,j);
                }
                f -= P[i][x[j]]*Q[x[j]][i];
                r += max_line[i];
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值