回溯法搜索排列数

排列数

排列数:举个例子,1, 2, 3的排列数就是:
3 1 2
3 2 1
1 3 2
1 2 3
2 1 3
2 3 1
那么如何得到这个排列数呢?看这个回溯法搜索排列数框架:

void Backtrack(int t) {
	if (t > n) {
		output();
	}
	else {
		for (int i = t; i <= n; i++) {
			Swap(x[t], x[i]);
			if (Constraint(t) && Bound(t)) {
				Backtrack(t + 1);
			}
			Swap(x[t], x[i]);
		}
	}
}

用C++写出来就是:

#include <iostream>

using namespace std;

int a[10];


void Backtrack(int t) {
	if (t > 3) {
		for (int i = 0; i < 3; i++) {
				cout << a[i] << " ";
			}
			cout << endl;
		return ; 
	}
	else {
		for (int i = t; i <= 3; i++) {
			int temp = a[i - 1];
			a[i - 1] = a[t - 1];
			a[t - 1] = temp;
			Backtrack(t + 1);
			temp = a[i - 1];
			a[i - 1] = a[t - 1];
			a[t - 1] = temp;
		}
	}
}

int main() {
	for (int i = 0; i < 3; i++) {
		cin >> a[i];
	}
	Backtrack(1);
}

运行例子:

1 2 3

3 1 2
3 2 1
1 3 2
1 2 3
2 1 3
2 3 1
排列数的应用
8604 运动员最佳配对问题

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

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

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

如下面sample的数据:

P=

10 2 3

2 3 4

3 4 5

Q=

2 2 2

3 5 3

4 5 1

最大的男女双方竞赛优势总和为:102 + 45 + 4*3 = 52

最佳搭配为:(女1,男1)(女2,男3)(女3,男2)

解析

对于这个问题,我们可以对男生进行全排列,然后与女生相乘。

源代码
#include <iostream>

using namespace std;

// 这个表示个数、m表示男生,w表示女生
int n, m[20][20], w[20][20];
// 表示总分数
int sum = 0, a[20];

void Backtrack(int t) {
	if (t > n) {
		int temp = 0;
		for (int i = 0; i < n; i++) {
			temp += m[a[i]][i] * w[i][a[i]];
		}
		if (temp > sum) {
			sum = temp;
		}
	}
	else {
		for (int i = t; i <= n; i++) {
			int temp = a[i - 1];
			a[i - 1] = a[t - 1];
			a[t - 1] = temp;
			Backtrack(t + 1);
			temp = a[i - 1];
			a[i - 1] = a[t - 1];
			a[t - 1] = temp;
		}
	}
}

int main(){
	cin >> n;
	for (int i = 0; i < n; i++) {
		a[i] = i;
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> m[i][j];
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> w[i][j];
		}
	}
	Backtrack(1);
	cout << sum;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值