工作分配问题(dfs)

题目

背景描述

设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为Cij。试设计一个算法,为每一个人都分配一件不同的工作,并使总费用达到最小。 
设计一个算法,对于给定的工作费用,计算最佳工作分配方案,使总费用达到最小。

输入

第一行有1个正整数n (1≤n≤20)。接下来的n行,每行n个数,第i行表示第i个人各项工作费用。

输出

计算出的最小总费用

样例输入

3
4 2 5
2 3 6
3 4 5

样例输出

9

非优化部分

分析

最基本的思路就是遍历所有的情况,计算出最小的花费。思路可以类似N皇后问题,设一个一维数组记录第i个岗位由第j个人来完成,然后计算出该方案所需的费用,与最当前的最小值比较。但是这种算法和for循环遍历情况是一样的,时间复杂度为O(2^n)。

代码

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

ll n,minn=INT_MAX;
ll a[25][25];
ll ans[25];
ll sum=0;

bool judge(int t)//判断填入的工作是不是满足要求;
{
	for(int i=0;i<t;i++)
	{
		if(ans[i]==ans[t])//判断与之前已经填入的工作是否有冲突,进而判断出填入的数据是否合法;
		return false;
	}
	return true;
}

void dfs(int t)
{
	if(t==n)//深搜终止条件;
	{
		sum=0;
		for(int i=0;i<n;i++)
		{
			sum+=a[i][ans[i]];//求该种情况下花费的费用;
		}
		minn=min(minn,sum);//比较该情况的费用和当前的最小值,使得minn的值一直是最小的
		return;
	}
	for(int i=0;i<n;i++)
	{
		ans[t]=i;//循环填入工作编号;
		if(judge(t))//判断是否合法;
		{
			dfs(t+1);//递归深搜,下一个工人的工作编号;
		}
	}
}

int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			cin>>a[i][j]; 
		}
	}
	dfs(0);
	cout<<minn;//输出最小的花费值;
	return 0;
}

这一代码很显然跑的时间是很长的,很容易超时;

优化部分

优化分析

引用子集和问题的思路,同样我们设一个数组,来标记该工作是否已经有人去完成。深搜时间我们加入一个变量来求和,同时在我们的dfs函数中加入一个判断条件,如果当前的费用和已经超过当前确定的最小值,则停止深搜来剪枝,减少不必要的过程,节省时间。

优化代码

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

ll n,minn=INT_MAX;//定义全局变量n,和一个值非常大的minn来表示当前的最小值; 
ll a[25][25];//定义一个二位数组表示每一位的工人完成每一项工作所需要的费用; 
ll flag[25];//标记工作是否有人来做; 

void dfs(int t,int sum)//深搜函数,t表示工人的编号,sum计算该方案所需要花费的费用; 
{
	if(sum>=minn)//如果当前费用已经大于当前的最小值,则剪去这一枝; 
		return;
	if(t==n)//深搜结束条件 
	{
		if(minn>sum)//如果当前的最小值大于该方案的费用,则替换minn的值
		//这一判断条件可以不用加,因为之前已经将大于minn的sum全部去除,这里就可以直接替换minn的值; 
		minn=sum;
	}
	for(int i=0;i<n;i++)//循环全全部的工作编号,是的所有工作都有人参与; 
	{
		if(flag[i]==0)//判断该工作是否已经有工人去做; 
		{
			flag[i]=1;//将这一工作标记为1,即这一工作已经有人去参加了; 
			dfs(t+1,sum+a[t][i]);//深搜下一名工人; 
			flag[i]=0;//回溯; 
		}
	}
}

int main()
{
	scanf("%lld",&n);
	for(int i=0;i<n;i++)
	{
		flag[i]=0;//将所有工作都标记为无人参与; 
		for(int j=0;j<n;j++)
		{
			scanf("%lld",&a[i][j]);
		}
	}
	dfs(0,0);
	printf("%lld",minn);
	return 0;
}

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
任务分配问题是一种经典的优化问题,它的目标是在一个固定的时间内完成尽可能多的任务。蛮力法是一种简单直接的算法,它可以用来解决任务分配问题。 蛮力法的基本思想是将所有可能的任务分配方案都枚举一遍,并计算每种方案所能完成的任务数,最后选取完成任务数最多的方案作为最优解。 下面是使用蛮力法解决任务分配问题的示例代码: ```c #include <stdio.h> #define MAXN 10 int n; // 任务数 int c[MAXN][MAXN]; // 任务完成时间矩阵 int x[MAXN]; // 当前任务分配方案 int bestx[MAXN]; // 最优任务分配方案 int bestc; // 最优完成任务数 // 计算当前任务分配方案所能完成的任务数 int calculate() { int sum = 0; for (int i = 0; i < n; i++) { sum += c[i][x[i]]; } return sum; } // 枚举所有任务分配方案 void dfs(int k) { if (k == n) { int c = calculate(); if (c < bestc) { bestc = c; for (int i = 0; i < n; i++) { bestx[i] = x[i]; } } return; } for (int i = 0; i < n; i++) { if (x[i] == -1) { x[i] = k; dfs(k + 1); x[i] = -1; } } } int main() { // 读入任务完成时间矩阵 scanf("%d", &n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { scanf("%d", &c[i][j]); } } // 初始化任务分配方案和最优完成任务数 for (int i = 0; i < n; i++) { x[i] = -1; } bestc = 1e9; // 枚举所有任务分配方案 dfs(0); // 输出最优任务分配方案和最优完成任务数 printf("bestx: "); for (int i = 0; i < n; i++) { printf("%d ", bestx[i]); } printf("\nbestc: %d\n", bestc); return 0; } ``` 在上面的示例代码中,我们使用深度优先搜索枚举所有的任务分配方案,并计算每种方案所能完成的任务数。最后选取完成任务数最少的方案作为最优解,并输出最优任务分配方案和最优完成任务数。 上述代码中使用了邻接矩阵来表示任务完成时间,如果使用邻接表来表示,则可以进一步优化时间复杂度

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值