搜索,问题 C: 【搜索与回溯】分工问题

题目

【例5.6】设有A,B,C,D,E五人从事J1,J2,J3,J4,J5五项工作,每人只能从事一项,他们的效益如下。

    每人选择五项工作中的一项,在各种选择的组合中,找到效益最高的的一种组合输出。

输入

    无输入。

输出

    前面五行,输出五人分配的工作;

    最后一行输出:supply:最佳效益值。(参考样例输出)

样例输出 复制
A:J5
B:J3
C:J4
D:J1
E:J2
supply:50

做了几个题之后,发现模板1和模板2是真好用,这题直接写出模板1的代码 。

题解 

模板1

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

int ans[10], c[10];

char nb[] = {'A', 'B', 'C', 'D', 'E'};// 根据输出格式的标记数组

int mmp[6][6] = {{0, 13, 11, 10, 4, 7}, 
				{0, 13, 10, 10, 8, 5}, 
				{0, 5, 9, 7, 7, 4}, 
				{0, 15, 12, 10, 11, 5}, 
				{0, 10, 11, 8, 8, 4}};

int sum = 0;

int res = 0;

bool vis[10];

void print(){
	for(int i = 0;i < 5;i ++){
		cout << nb[i] << ':' << 'J' << c[i] <<'\n';
	}
	cout << "supply:" << res << '\n';
}

void fcx(int d){// 
	for(int j = 1;j <= 5;j ++){
		if(vis[j])continue;
		sum += mmp[d][j];
		vis[j] = true;
		ans[d] = j;
		if(d == 4){
			if(sum > res){
				res = sum;
				memcpy(c, ans, sizeof ans);
			}
		}else {
			fcx(d + 1);
		}
		vis[j] = false;
		sum -= mmp[d][j];
	}
}

int main(){
	memset(vis, 0, sizeof vis);
	fcx(0); // dfs(1) 
	print();
	return 0;
}

模板2

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

int ans[10], c[10], res, sum;

bool vis[10];

char np[] = {'x', 'A', 'B', 'C', 'D', 'E'};

int mp[6][6] = {{0, 13, 11, 10, 4, 7}, 
				{0, 13, 10, 10, 8, 5}, 
				{0, 5, 9, 7, 7, 4}, 
				{0, 15, 12, 10, 11, 5}, 
				{0, 10, 11, 8, 8, 4}};

void print(){
	for(int i = 1;i <= 5;i ++){
		cout << np[i] << ':' << 'J' << ans[i] << '\n';
	}
	cout << "supply:" << res;
} 

void fcx(int d){
	if(d == 6){
		if(sum > res){
			res = sum;
			memcpy(ans, c, sizeof c);
		}
	}else {
		for(int j = 1;j <= 5;j ++){
			if(!vis[j]){
				vis[j] = true;
				sum += mp[d - 1][j];
				c[d] = j;
				fcx(d + 1);
				sum -= mp[d - 1][j];
				vis[j] = false;
			}
		}
	}
}

int main(){
	fcx(1);
	print();	
	return 0;
}

奇怪的方法 

 可以用枚举类似蒙特卡洛模拟的思想来解决

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

char nb[] = {'A', 'B', 'C', 'D', 'E'};
int mmp[6][6] = {{0, 13, 11, 10, 4, 7}, 
				{0, 13, 10, 10, 8, 5}, 
				{0, 5, 9, 7, 7, 4}, 
				{0, 15, 12, 10, 11, 5}, 
				{0, 10, 11, 8, 8, 4}};

int ans = 0;
int p[10];

void print(){
	for(int i = 0;i < 5;i ++){
		cout << nb[i] << ":J" << p[i] << '\n';
	}
	cout << "supply:" << ans << '\n';
}

void randperm(int Num)
{	
	int res = 0;
	vector<int> temp;
	for (int i = 0; i < Num; ++i)
	{
		temp.push_back(i + 1);
	}
	random_shuffle(temp.begin(), temp.end());
 
	for (int i = 0; i < temp.size(); i++)
	{
		res += mmp[i][temp[i]];
	}
	if(res > ans){
		ans = res;
		for(int i = 0;i < temp.size();i ++){
//			cout << temp[i] << ' ';
			p[i] = temp[i];
		}
//		cout <<'\n';
	}
}
 

int main(){
	int t = 0;
	srand((int)time(0));// 随机数随时间变化
	for(int i = 1;i <= 1000;i ++){// 蒙特卡洛思想,可以将i的最大值可以设置小一点,如20,
		randperm(5);//运行多次发现,有时过,有时不过。纯随机,看人品
	}
	print();
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值