问题描述:

有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个人完成的问题相关推荐

  1. 3. 工作分配问题(回溯法)设有n件工作分配给n个人。。。

    问题描述: 设有n件工作分配给n个人.将工作i分配给第j个人的费用为cij,请设计算法,为每个人都分配1件不同的工作,并使得总费用达到最小. 实现提示:该问题的解空间是一棵排列树,可用搜索排列树的回溯 ...

  2. 批处理作业调度问题 ——回溯法详解

    1.问题描述 每一个作业Ji都有两项任务分别在2台机器上完成.每个作业必须先有机器1处理,然后再由机器2处理.作业Ji需要机器j的处理时间为tji.对于一个确定的作业调度,设Fji是作业i在机器j上完 ...

  3. leetcode2021年度刷题分类型总结(三)回溯法 (python)

    主要参考:代码随想录 分为三个部分对回溯法进行总结 1.组合 例一:77. 组合 组合问题关键在于[1,4]和[4,1]算作重复答案,也即取数时往前推进,取到4时不能回头取1,所以每次都要记录取到的位 ...

  4. 算法分析五:回溯法与分⽀限界法

    一.回溯法 1. 基本思想与解题步骤 基本思想: 把问题的解空间转化成了图或者树的结构表⽰,然后使⽤深度优先搜索策略进⾏遍历,遍历的过程中记录和寻找所有可⾏解或者最优解. 解题步骤: 针对所给问题,定 ...

  5. 五大常用算法——分治法,动态规划,回溯法,分支界限法,贪心算法

    (1) 分治法 将一个难以直接解决的大问题,分割成一些规模较小的相同问题 快速排序 快排也是分治的一个实例,快排每一趟会选定一个数,将比这个数小的放左面,比这个数大的放右面, 然后递归分治求解两个子区 ...

  6. 分治法、动态规划法、回溯法、贪心法简单叙述

    1.分治法特征:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决:否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问 ...

  7. 回溯法、分枝限定法--求解N个杯子分酒问题

    n(<20)个没有刻度.容量分别为A1~ An的酒杯,初始装酒量分别为s1~ sn,求用最少次数倒成D1~ Dn的倒酒过程,其中A1~ An, s1~ sn, D1~Dn数据可以固定在程序中. ...

  8. 几个常见的简单的算法(暴力法,递推法,枚举法,递归法,分治法,贪心法,回溯法)

    最近在学习算法相关知识. 通过买的视频教程了解到了一些简单的算法,为了加深感悟,同时也为了理解,将这几个常见的算法的定义进行记录. 算法是程序的灵魂,也可以认为是程序最重要的部分. 在通过算法解决问题 ...

  9. 图形结构:遍历模型,分治法,动态规划,回溯法,BFS,DFS

    图形结构,是树形结构的扩展. 我们在回溯法里面了解到几种结构:二叉树,排列树,完全n叉树,这几种解空间类型,都可以直接使用回溯法的框架解决. 二叉树,排列树,完全n叉树,都可以看成x叉树的变形,而图形 ...

最新文章

  1. java 方法返回的值,java方法返回值问题
  2. oracle 容器切换,oracle12c 多租户管理四(容器连接切换)
  3. scala把序列分解成子集(group by,partition)
  4. linux db2 ssl,IBM DB2 Content Manager V83与手工配置SSL
  5. C# JScript.Eval使用
  6. oracle 数据库回闪,各种数据库闪回的总结
  7. Java预科篇2-环境搭建
  8. jsch 长连接_广濑连接器DF13
  9. db2 license过期
  10. jQuery size()函数
  11. python基础-字符串(6)
  12. 深入浅出SCSI子系统(八)SCSI错误恢复
  13. python dicom 三维重建_DICOM HTML5 Viewer中的真三维重建
  14. 菜鸟点评-FILCO 忍者二代机械键
  15. 技术分享 | 如何实现小程序与 App 的跳转
  16. Trained Ternary Quantization
  17. 基于网易云信WebRTC的Web音视频实现
  18. CREO:CREO软件之零件【渲染】之对三维零件实现渲染图文教程之详细攻略
  19. Uncaught SyntaxError: Not available in legacy mode
  20. python字典程序题_Python练习:字典

热门文章

  1. opencv中 当你直接把别人的程序拖进去无法运行时 解决方法
  2. 3.1.3 训练/开发/测试集的问题以及注意事项
  3. springboot 替换tomcat_Springboot (二十八)云配置服务器
  4. springboot配置
  5. Confluence 6 使用 WebDAV 客户端来对页面进行操作
  6. 记录自己最近犯得一些傻事
  7. 3451: Tyvj1953 Normal 点分治 FFT
  8. P1681 最大正方形 Iand II
  9. Androidstudio 使用git插件提交代码
  10. python之列表、字典、集合