最佳运动员配对问题:回溯法

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
//最佳运动员配对问题
/*
剪枝:
1.由男性运动员选择女性运动员进行配对。根据输入,每个男性都有最佳的女运动员与之配对。
若[当前还未配对的男性运动员均选择最佳配对(不考虑女运动员是否已配对)时的配对值之和]
与[当前已完成配对的男运动员的配对值之和]相加仍未能优于当前最优解,则该子树上不会存在
最优解,剪枝。
2.每名女性运动员只能和一名男性运动员配对
*/
const int N = 10;
int P[N][N];
int Q[N][N];
int n;
int Max[N];//贪心最大配对记录(提前设置完毕)
//
int pq[N];//女远动员的排列(第i位男士配第pq[i]位女性)
int endsum[N];//结果配对记录
int Maxsum;//当前配对和
int Maxcount;//(最终)最大配对和
//
void getMaxsum(int x)//x排列树层数
{
    if(x>n){
        if(Maxsum>Maxcount){
            Maxcount=Maxsum;
            for(int i=1;i<=n;i++){
                endsum[i]=pq[i];//最优解替换
            }
        }
        return;
    }
    int cnt=0;//求出剩余最大贪心配对和
    for(int i=x+1;i<=n;i++){
        cnt=cnt+Max[i];
    }
    
    for(int j=x;j<=n;j++){
        swap(pq[j],pq[x]);
        Maxsum+=P[x][pq[x]]*Q[pq[x]][x];
        if((cnt+Maxsum)>Maxcount)//剪枝
        {
            getMaxsum(x+1);
        }
        Maxsum-=P[x][pq[x]]*Q[pq[x]][x];
        swap(pq[x],pq[j]);
    }  
}

int main()
{
    cout<<"please enter the number of the athletes"<<endl;
    cin>>n;
    //cout<<"please enter the P matrix"<<endl;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>P[i][j];
        }
    }
    //cout<<"please enter the Q matrix"<<endl;
    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++){
        pq[i]=i;
    }
    //设置Max数组
    for(int i=1;i<=n;i++){
        int temp=0;
        for(int j=1;j<=n;j++){
            if(P[i][j]*Q[j][i]>temp)temp=P[i][j]*Q[j][i];
        }
        Max[i]=temp;
    }
    getMaxsum(1);
    //结果输出
    cout<<Maxcount<<endl;
    for(int i=0;i<n;i++){
        cout<<endsum[i+1]<<" ";
    }cout<<endl;
    system("pause");
    return 0;
}
/*
3
10 2 3
2 3 4
3 4 5
2 2 2
3 5 3
4 5 1
*/

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值