這道題可以看為排列數的一個典型模塊
一、算法實現題:
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。
輸入文件示例 輸出文件示例
intput.txt output.txt
3 52
10 2 3
2 3 4
3 4 5
2 2 2
3 5 3
4 5 1
二、解題思路
1、求問題的解空間
對於n個男運動員,從第1個開始搭配女運動員:第1個有n種搭配方法,第2個有n-1種搭配方法……第n個有n-(n-1)種搭配方法;根據問題給出的示例:輸入n的值為3,表示男女運動員各有3名;
男運動員 1 2 3按順序搭配女運動員,他們分別對應的女運動員可以是:
女運動員 1 2 3、1 3 2、2 1 3、2 3 1、3 1 2、3 2 1
所以其解空間是{(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)},整個問題可看成是1,2,3的全排列問題,將解空間組織成一棵排列樹如下
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 int p[100][100]; 5 int q[100][100]; 6 int x[100]; 7 int best[100]; 8 int answer=0; 9 void swap(int &a,int &b){ 10 int temp; 11 temp=a; 12 a=b; 13 b=temp; 14 } 15 void update(){ 16 int sum=0; 17 for(int i=1;i<=n;i++){ 18 sum+=p[i][x[i]]*q[x[i]][i]; 19 } 20 if(sum>answer){ 21 answer=sum; 22 for(int i=1;i<=n;i++){ 23 best[i]=x[i]; 24 } 25 } 26 } 27 void backtrace(int level){ 28 if(level>n){ 29 update(); 30 31 } 32 else{ 33 for(int i=level;i<=n;i++){ 34 swap(x[level],x[i]); 35 backtrace(level+1); 36 swap(x[level],x[i]); 37 } 38 } 39 } 40 int main() 41 { 42 43 cin >> n; 44 memset(p,0,sizeof(p)); 45 memset(q,0,sizeof(q)); 46 memset(best,0,sizeof(best)); 47 memset(x,0,sizeof(x)); 48 for(int i=1;i<=n;i++){ 49 for(int j=1;j<=n;j++){ 50 cin >> p[i][j]; 51 } 52 } 53 for(int i=1;i<=n;i++){ 54 for(int j=1;j<=n;j++){ 55 cin >> q[i][j]; 56 } 57 } 58 for(int i=1;i<=n;i++){ 59 x[i]=i; 60 } 61 backtrace(1); 62 cout << answer << endl; 63 for(int i=1;i<=n;i++){ 64 cout << best[i]<< " "; 65 } 66 return 0; 67 }