回溯法实现n份作业分配给n个人完成的问题
问题描述:
有n份作业分配给n个人去完成,每人完成一份作业。假定第i个人完成第j份作业需要花费cij时间, cij>0,1≦i,j≦n。试设计一个回溯算法,将n份作业分配给n个人完成,使得总花费时间最短。
问题思路:
n分作业分配给n个人,共有A!中排列方式,深度优先遍历其排列数,如果遍历的路径已经比当前最小的话费则舍弃对当前路径的遍历,返回上层节点,寻找合适的路径,即回溯,如果最后可行解比当前的最小话费小,那么就更行最佳的作业安排顺序,同时更新最小的耗费时间。
算法描述:
t :递归的层数
curr :当前的实际时间花费
bestw :当前的最优的时间消耗
arrange:任务的安排
Backtrack(t)
if t>=n
then if curr<bestw
then bestw <- curr
update arrange
ouput(arrange)
else do
for t to n do
swap the arrange of t and i
compute the current cost of the arrange
if curr<bestw then backtrack(t+1)
swap the arrange of t and i
give back the arrange t
数据结构的选择:使用数组是想对任务工作的安排
算法的复杂度分析:O(n!)
算法的实现:
//backtrack.h #include <stdio.h> #include <stdlib.h> #include <limits.h>void backtrack(int t);//t为排列树的深度 void getRslt(char filename[]);//从文件中读取数据,求解结果 void output(int *arrange);//输入最终的任务分配结构 void swap(int &a,int &b);//交换数组中的两个元素//backtrack.cpp #include "backtrack.h" #include <malloc.h>int *arrange;// 最终的作业分配安排 int dataSize;//任务的个数 和人员的个数相同 int **cost;//邻接矩阵用于存储每个人完成每份作业所需要的时间消耗 int bestw=INT_MAX;//初始为最大的整数 若出现小的则更行 int curr=0; int *best_arrange;void getRslt(char filename[]) {FILE *fp;int i=0;int j=0; // curr=0; fp=fopen(filename,"r");if (!fp){printf("error,can not open the file%s",filename);return;}fscanf(fp,"%d",&dataSize);//开辟数据的空间,并将数据存在空间中best_arrange=(int*)malloc(dataSize*sizeof(int));cost=(int**)malloc(dataSize*sizeof(int*));for (i=0;i<dataSize;i++){cost[i]=(int*)malloc(dataSize*sizeof(int));if (!cost[i]){printf("error can not malloc the space!");}}for (i=0;i<dataSize;i++){for (j=0;j<dataSize;j++){fscanf(fp,"%d",&cost[i][j]);}}arrange=(int *)malloc(dataSize*sizeof(int));if (!arrange){printf("error,can not malloc a new space!");}for (i=0;i<dataSize;i++){arrange[i]=i;}backtrack(0);output(best_arrange);printf("the best time is:%d\n",bestw);//释放开辟的空间避免内存泄露 free(arrange);arrange=NULL;dataSize=0;for (i=0;i<dataSize;i++){free(*(cost+i));}free(cost);cost=NULL;bestw=INT_MAX;curr=0;free(best_arrange);best_arrange=NULL; } void backtrack(int t)//t表示第t个作业cost[i][j]第i个人完成第j个任务所要完成的时间 {int i=0;int j=0;if (t>=dataSize)//已经达到叶子节点 递归出口 {if (curr<bestw){bestw=curr;for (j=0;j<dataSize;j++){best_arrange[j]=arrange[j];}}return;}elsefor (i=t;i<dataSize;i++)//选取要递归的节点,依次递归节点的每一个孩子 {swap(arrange[t],arrange[i]);//把第t个任务安排给arrang[i] 把第i个任务地第arrange[t]curr=curr+cost[arrange[t]][t];//当前时间家让把第t个任务我交给第arrange[i]所花费的时间if(curr>bestw)//当前的时间消耗已经超过当前的最佳时间 此时不用再递归其子节点 可以直接返回 { curr=curr-cost[arrange[t]][t];swap(arrange[t],arrange[i]);continue;//本次循环结束 }backtrack(t+1);//递归一直到叶节点curr=curr-cost[arrange[t]][t];//如果没有解则回溯 swap(arrange[t],arrange[i]);} }void output(int *arrange)//打印最终的结果 {int i=0;printf("the arrange of the work is:\n");for (i=0;i<dataSize;i++){printf("the task %d is arranged to %d\n",(i+1),arrange[i]+1);}}void swap(int &a,int &b)//交换两个数的数值 {int temp;temp=a;a=b;b=temp; }//main.cpp #include "backtrack.h" #include <string.h>int main() {char filename[256]="ddddd";while (1){printf("please input the name of data file(input ‘exit’to quit the program):\n");gets(filename);if (!strcmp(filename,"exit")){break;}getRslt(filename);}return 1; }
转载于:https://www.cnblogs.com/liwenzhu/p/3504287.html
回溯法实现n份作业分配给n个人完成的问题相关推荐
- 3. 工作分配问题(回溯法)设有n件工作分配给n个人。。。
问题描述: 设有n件工作分配给n个人.将工作i分配给第j个人的费用为cij,请设计算法,为每个人都分配1件不同的工作,并使得总费用达到最小. 实现提示:该问题的解空间是一棵排列树,可用搜索排列树的回溯 ...
- 批处理作业调度问题 ——回溯法详解
1.问题描述 每一个作业Ji都有两项任务分别在2台机器上完成.每个作业必须先有机器1处理,然后再由机器2处理.作业Ji需要机器j的处理时间为tji.对于一个确定的作业调度,设Fji是作业i在机器j上完 ...
- leetcode2021年度刷题分类型总结(三)回溯法 (python)
主要参考:代码随想录 分为三个部分对回溯法进行总结 1.组合 例一:77. 组合 组合问题关键在于[1,4]和[4,1]算作重复答案,也即取数时往前推进,取到4时不能回头取1,所以每次都要记录取到的位 ...
- 算法分析五:回溯法与分⽀限界法
一.回溯法 1. 基本思想与解题步骤 基本思想: 把问题的解空间转化成了图或者树的结构表⽰,然后使⽤深度优先搜索策略进⾏遍历,遍历的过程中记录和寻找所有可⾏解或者最优解. 解题步骤: 针对所给问题,定 ...
- 五大常用算法——分治法,动态规划,回溯法,分支界限法,贪心算法
(1) 分治法 将一个难以直接解决的大问题,分割成一些规模较小的相同问题 快速排序 快排也是分治的一个实例,快排每一趟会选定一个数,将比这个数小的放左面,比这个数大的放右面, 然后递归分治求解两个子区 ...
- 分治法、动态规划法、回溯法、贪心法简单叙述
1.分治法特征:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决:否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问 ...
- 回溯法、分枝限定法--求解N个杯子分酒问题
n(<20)个没有刻度.容量分别为A1~ An的酒杯,初始装酒量分别为s1~ sn,求用最少次数倒成D1~ Dn的倒酒过程,其中A1~ An, s1~ sn, D1~Dn数据可以固定在程序中. ...
- 几个常见的简单的算法(暴力法,递推法,枚举法,递归法,分治法,贪心法,回溯法)
最近在学习算法相关知识. 通过买的视频教程了解到了一些简单的算法,为了加深感悟,同时也为了理解,将这几个常见的算法的定义进行记录. 算法是程序的灵魂,也可以认为是程序最重要的部分. 在通过算法解决问题 ...
- 图形结构:遍历模型,分治法,动态规划,回溯法,BFS,DFS
图形结构,是树形结构的扩展. 我们在回溯法里面了解到几种结构:二叉树,排列树,完全n叉树,这几种解空间类型,都可以直接使用回溯法的框架解决. 二叉树,排列树,完全n叉树,都可以看成x叉树的变形,而图形 ...
最新文章
- java 方法返回的值,java方法返回值问题
- oracle 容器切换,oracle12c 多租户管理四(容器连接切换)
- scala把序列分解成子集(group by,partition)
- linux db2 ssl,IBM DB2 Content Manager V83与手工配置SSL
- C# JScript.Eval使用
- oracle 数据库回闪,各种数据库闪回的总结
- Java预科篇2-环境搭建
- jsch 长连接_广濑连接器DF13
- db2 license过期
- jQuery size()函数
- python基础-字符串(6)
- 深入浅出SCSI子系统(八)SCSI错误恢复
- python dicom 三维重建_DICOM HTML5 Viewer中的真三维重建
- 菜鸟点评-FILCO 忍者二代机械键
- 技术分享 | 如何实现小程序与 App 的跳转
- Trained Ternary Quantization
- 基于网易云信WebRTC的Web音视频实现
- CREO:CREO软件之零件【渲染】之对三维零件实现渲染图文教程之详细攻略
- Uncaught SyntaxError: Not available in legacy mode
- python字典程序题_Python练习:字典