回溯--最佳匹配问题

运动员最佳分配问题(回溯)

题目:
在这里插入图片描述
在这里插入图片描述

这道题我的第一想法就是跟n皇后问题类似,所以实际在写的过程中我也使用了n皇后的模板,进行了简单的修改,即在判断位置的时候只要不是在同一行或同一列即可,无需要求不能在同一斜线上。最后利用记录下来的行列来进行运算该条路线的匹配度,对最大值进行更新即可。
我觉得计算匹配度这点是可以在进行路线匹配时可以同时更新计算的,但是我自己写的时候失败了,没有找到合适的方法。如果有大佬有想法,还请指教。
还有一个问题就是,这道题的要求是(1<=n<=20),但是我的程序执行下来基本上在十一二以后就会死掉,不是死循环吧,只是因为时间复杂度过高而导致的,我在网上也找了很多被人的代码进行运算尝试,但结果也拆不了多少,基本超过十多一点就死掉,不管是递归还是迭代。如果之后能够解决这个问题,我会重新更新,这里先记录一下吧。

因为是第一次发帖,不太会用,代码也是重新打了一遍因为没法复制粘贴所以不确定有没有错。因为我们老师要求要调用时间函数来分析时间复杂度,然后数据是随机生成的,还是取到了20,书上的案例是能过的。
这里是贴的代码:

#include<bits/stdc++.h>
using namespace std;

int x[21],o[21][21];
int maxn,n;

bool place(int k)
{
	for(int i = 1; i < k; i ++)
		if(x[k] == x[i])
			return false;
	return true;
}

void optimal()
{
	x[1] = 0;
	int t = 1;
	int cmp = 0;
	while(t > 0)
	{
		x[t]++;

		while(x[t] <= n && !place(t))
			x[t] ++;

		if(x[t] <= n)
		{
			if(t == n)
			{
				cmp = 0;
				for(int i = 1; i <= n; i ++)
					cmp += o[i][x[i]];

				if(maxn < cmp)
					maxn = cmp;
			}
			else
				x[++t] = 0;
		}
		else
			t--;
	}
}

int main()
{
	ofstream in("input.txt");
	ofstream out("output.txt");

	srand(time(NULL));
	int T = 20; //20组数据
	while(T--)
	{
		n = rand()%20 + 1;
		in << n << endl;
		int p[n+1][n+1],q[n+1][n+1];
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1 ; j <= n; j ++)
			{
				p[i][j] = rand()%100 +1;
				in << p[i][j] << " ";
			}
			in << endl;
		}
		for(int i = 1; i <= n; i ++)
		{
			for(int j = 1; j <= n; j++)
			{
				q[i][j] = rand()%100 + 1;
				in << q[i][j] << " ";
			}
			in << endl;
		}
		in << endl;

		clock_t start, end;
		double duration;
	
		start = clock(); //开始计时
		if(n == 1)
		{
			cout << p[1][1]*q[1][1] << endl;
			out << p[1][1]*q[1][1] << endl;
			continue;
		}
		
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= n; j++)
				o[i][j] = p[i][j] * q[i][j];//计算存储两人间的匹配度
		maxn = 0;
		memset(x, 0, sizeof(x));
		optimal();
		cout << maxn << endl;
		out << maxn << endl;
		end = clock();//结束计时
	
		duration = (double)(end - start)/CLOCKS_PER_SEC;
		cout << "TIME:" << duration << " seconds" << endl;
		system("pause"); //暂停
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值