动态规划-流水作业调度报告

合集下载

C++程序-流水作业调度

C++程序-流水作业调度

一、问题描述给定n个作业,每个作业有两道工序,分别在两台机器上处理。

一台机器一次只能处理一道工序,并且一道工序一旦开始就必须进行下去直到完成。

一个作业只有在机器1上的处理完成以后才能由机器2处理。

假设已知作业i在机器j上需要的处理时间为t[i,j]。

流水作业调度问题就是要求确定一个作业的处理顺序使得尽快完成这n个作业。

二、算法分析n个作业{1,2,…,n}要在由2台机器M和2M组成的流水线上完成加工。

每1个作业加工的顺序都是先在M上加工,然后在2M上加工。

1M和2M加工作业i所1需要的时间分别为t[i,1]和t[i,2], n1.流水作业调度问题要求确定这ni≤≤个作业的最优加工顺序,使得从第一个作业在机器M上开始加工,到最后一个1作业在机器M上加工完成所需的时间最少。

2从直观上我们可以看到,一个最优调度应使机器M没有空闲时间,且机器2M1的空闲时间是最少。

在一般情况下,机器M上会有机器空闲和作业积压两种情2况。

设全部作业的集合为}N=。

N2,1{n,....,S⊆是N的作业子集。

在一般情况下,机器M开始加工S中作业时,机器2M还在加工其他作业,要等时间t后才能利1用。

将这种情况下完成S中作业所需的最短时间计为),ST。

流水作业调度问题(t的最优解为)0,T。

(N1.证明流水作业调度问题具有最优子结构设a是所给n个流水作业的一个最优调度,它所需要的加工时间为']1),1([T a t +。

其中,'T 是在机器2M 的等待时间为]2),1([a t 时,安排作业)(),......,3(),2(n a a a 所需的时间。

记)}1({a N S -=,则我们可以得到])2),1([,('a t S T T =。

事实上,有T 的定义可知])2),1([,('a t S T T ≥.若])2),1([,('a t S T T >,设'a 是作业集S 在机器2M 的等待时间为]2),1([a t 情况下的一个最优调度。

操作系统作业调度实验报告

操作系统作业调度实验报告
#define getpch(type) (type*)malloc(sizeof(type))
#define NULL 0
int n;
float T1=0,T2=0;
int times=0;
struct jcb//作业控制块
{
char name[10]; //作业名
int reachtime; //作业到达时间
3、对每种调度算法都要求打印每个作业开始运行时刻、完成时刻、周转时间、带权周转时间,以及这组作业的平均周转时间及带权平均周转时间。
3)流程图:
二.最短作业优先算法
三.高响应比算法
图一.先来先服务流程图
4)源程序:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
{
if(m==3) //显示高响应比算法调度作业后的运行情况
{
printf("\n作业%s正在运行,估计其运行情况:\n",q->name);
printf("开始运行时刻:%d\n",q->starttime);
printf("完成时刻:%d\n",q->finishtime);
printf("周转时间:%f\n",q->cycletime);
struct jcb *next; //结构体指针
}*ready=NULL,*p,*q;
typedef struct jcb JCB;
void inize()//初始化界面
{
printf("\n\n\t\t*********************************************\t\t\n");

流水作业调度

流水作业调度

流水作业调度一、 可行性分析与项目开发计划n个作业}{n ,...2,1要在由2台机器M1和M2组成的流水线上完成加工。

每个作业的顺序都是现在M1上加工,然后再M2上加工。

M1和M2加工作业i 所需的时间分别是i a 和i b ,1<=i<=n.流水作业调度问题要求确定这n 个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需要的时间最少。

直观上,一个最优调度应该使得机器M1没有空闲时间,而且机器M2的空闲时间最少,在一般情况下,机器M2上会出现机器空闲和作业积压两种情况。

设全部作业的集合为N={1,2,…n}。

N S ⊆是N 的作业子集,在一般情况下,机器M1开始加工作业S 中作业时,机器M2还在加工其他作业,要等时间t 后才可以利用。

将这种情况下完成S 中作业所需要的最短时间记做T(S,t),则流水作业调度问题的最优值就是T(N,0).我们通过分析可以知道流水作业调度问题具有最优子结构的性质,因此考虑用动态规划算法自后向前来解决其最优问题。

这就需要通过建模来得出最优子结构的递归式子,从而设计算法求解最优值。

二、 需求分析1、 用户可以根据自己的需要输入想要进入流水线的作业数。

2、 用户可以输入这几个作业在机器M1和M2上的加工时间。

3、 由主函数调用流水作业调度的Johnson 算法来实现对流水作业的安排。

4、 输出经过Johnson 算法安排后的作业序列,这就是最终的一个最优调度。

三、 概要设计 总体设计:假定这n 个作业在机器M1上加工时间为i a ,在机器M2上加工时间为i b ,1<=i<=n. 由流水作业调度问题具有最优子结构性质可知,)}},{(min{)0,(i i b i N T a N T =+= 1<=i<=n 推广到一般情况下,})}0,m a x {},{({),(i a t b i S T a t S T i i -+-+= S i ∈ 式子中,}0,max{i a t -这一项是由于在机器M2上,作业i 必须在},max{i a t 时间之后才能开工,因此,在机器M1上完成作业加工i 之后,在机器还需要}0,max{},max{i i i i i a t b a a t b -+=-+时间完成对作业i 的加工。

操作系统实验报告作业调度

操作系统实验报告作业调度

操作系统实验报告作业调度操作系统实验报告:作业调度引言作业调度是操作系统中的重要部分,它负责管理和调度系统中的各种作业,以最大化系统资源的利用率和提高作业的执行效率。

在本次实验中,我们将探讨作业调度的基本原理和实现方法,并通过实验验证其效果。

实验目的本次实验的主要目的是通过实际操作,了解作业调度的基本原理和实现方法,掌握作业调度的相关算法,并通过实验验证其有效性。

实验内容1. 实现作业调度的基本算法在本次实验中,我们将实现作业调度的基本算法,包括先来先服务(FCFS)、最短作业优先(SJF)、优先级调度(Priority Scheduling)和多级反馈队列调度(Multilevel Feedback Queue Scheduling)等。

通过编写代码,模拟这些算法的执行过程,并观察它们的效果。

2. 实验验证我们将设计一些测试用例,通过模拟作业的执行过程,分别使用不同的作业调度算法,并比较它们的执行效果。

通过实验验证,我们将得出不同算法的优劣势,并分析其适用场景。

实验结果经过实验验证,我们得出以下结论:1. 先来先服务(FCFS)算法适用于作业执行时间相对均匀的情况,但可能会导致平均等待时间较长。

2. 最短作业优先(SJF)算法能够最大程度地减少平均等待时间,但可能会出现作业饥饿现象。

3. 优先级调度(Priority Scheduling)算法能够根据作业的优先级进行调度,适用于有明确优先级需求的情况。

4. 多级反馈队列调度(Multilevel Feedback Queue Scheduling)算法能够根据作业的执行情况动态调整优先级,适用于各种类型的作业。

结论作业调度是操作系统中的重要组成部分,不同的作业调度算法适用于不同的场景。

通过本次实验,我们深入了解了作业调度的基本原理和实现方法,掌握了不同算法的优劣势,并通过实验验证了它们的有效性。

这将对我们进一步深入学习操作系统和提高系统性能有着重要的意义。

动态规划算法实验报告

动态规划算法实验报告

动态规划算法实验报告实验标题1、矩阵连乘2、最长公共子序列3、最大子段和4、凸多边形最优三角剖分5、流水作业调度6、0-1背包问题7、最优二叉搜索树实验目的掌握动态规划法的基本思想和算法设计的基本步骤。

实验内容与源码1、矩阵连乘#include<iostream>#include<cstdlib>using namespace std;const int size=4;//ra,ca和rb,cb分别表示矩阵A和B的行数和列数void matriMultiply(int a[][4],int b[][4],int c[][4],int ra ,int ca,int rb ,int cb ){if(ca!=rb) cerr<<"矩阵不可乘";for(int i=0;i<ra;i++)for(int j=0;j<cb;j++){int sum=a[i][0]*b[0][j];for(int k=1;k<ca;k++)sum+=a[i][k]*b[k][j];c[i][j]=sum;}}void MatrixChain(int *p,int n,intm[][4],int s[][4]){for(int i=1;i<=n;i++) m[i][i]=0;//对角线for(int r=2;r<=n;r++)//外维for(int i=1;i<=n-r+1;i++)//上三角{int j=i+r-1;m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];s[i][j]=i;for(int k=i+1;k<j;k++){intt=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];if(t<m[i][j]){m[i][j]=t;s[i][j]=k;}}}}void Traceback(int i,int j,int s[][4]){if(i == j){cout<<"A"<<i;}else if(i+1 == j){cout<<"(A"<<i<<"A"<<j<<")";}else{cout<<"(";Traceback(i,s[i][j],s);Traceback(s[i][j]+1,j,s);cout<<")";}int main(){int w;cout<<"矩阵个数:";cin>>w;int p[w],s[w][w];cout<<"输入矩阵A1维数:";cin>>p[0]>>p[1];for(int i=2 ; i<=w ; i++){int m = p[i-1];cout<<"输入矩阵A"<<i<<"维数:";cin>>p[i-1]>>p[i];if(p[i-1] != m){cout<<endl<<"维数不对,矩阵不可乘!"<<endl;exit(1);}Traceback(1,w,s);return 0;}运行结果2、最长公共子序列#include<cstring>#include<iostream>#define N 100using namespace std;//str1存储字符串x,str2存储字符串y char str1[N],str2[N];//lcs存储最长公共子序列char lcs[N];//c[i][j]存储str1[1...i]与str2[1...j]的最长公共子序列的长度int c[N][N];//flag[i][j]==0为str1[i]==str2[j] //flag[i][j]==1为c[i-1][j]>=s[i][j-1] //flag[i][j]==-1为c[i-1][j]<s[i][j-1] int flag[N][N];//求长度int LCSLength(char *x, char *y) {int i,j;//分别取得x,y的长度int m = strlen(x);int n = strlen(y);for(i=1;i<=m;i++)c[i][0] = 0;for(i=0;i<=n;i++)c[0][i] = 0;for(i=1;i<=m;i++)for(j=1;j<=n;j++){if(x[i-1]==y[j-1]){c[i][j] = c[i-1][j-1] +1;flag[i][j] = 0;}else if(c[i-1][j]>=c[i][j-1]){c[i][j] = c[i-1][j];flag[i][j] = 1;}else{c[i][j] = c[i][j-1];flag[i][j] = -1;}}return c[m][n];}//求出最长公共子序列char* getLCS(char *x, char *y,int len,char *lcs){int i = strlen(x);int j = strlen(y);while(i&&j){if(flag[i][j]==0){lcs[--len] = x[i-1];i--;j--;}else if(flag[i][j]==1)i--;elsej--;}return lcs;}int main(){int i;cout<<"请输入字符串x:"<<endl;cin>>str1;cout<<"请输入字符串y:"<<endl;cin>>str2;int lcsLen = LCSLength(str1,str2);cout<<"最长公共子序列长度:"<<lcsLen<<endl;char *p =getLCS(str1,str2,lcsLen,lcs);cout<<"最长公共子序列为:";for(i=0;i<lcsLen;i++)cout<<lcs[i]<<" ";return 0;}运行结果3、最大子段和//分治法求最大子段和#include<iostream>using namespace std;int MaxSubSum(int *a,int left,int right) {int sum=0;if(left==right)sum=a[left]>0?a[left]:0;else{int center = (left+right)/2;//最大子段和在左边intleftsum=MaxSubSum(a,left,center);//最大子段和在右边intrightsum=MaxSubSum(a,center+1,right);//最大子段和在中间int s1=0;int lefts=0;for(int i=center;i>=left;i--){lefts+=a[i];if(lefts>s1) s1=lefts;}int s2=0;int rights=0;for(int i=center+1;i<=right;i++){rights+=a[i];if(rights>s2) s2=rights;}sum=s1+s2;//前后子段和相加//判断最大子段和if(sum>leftsum)sum=leftsum;if(sum>rightsum)sum=rightsum;}return sum;}int MaxSum(int *a,int n){return MaxSubSum(a,1,n-1);}int main(){int a[8]={2,-3,-5,4,1,7,1,-5};cout<<"最大子段和为:"<<MaxSum(a,8);return 0;}//动态规划法#include<iostream>using namespace std;int MaxSum(int *a,int n){int sum=0,b=0;for(int i=1;i<n;i++)//此处不能=n,{if(b>0) b+=a[i];else b=a[i];if(b>sum) sum=b;}return sum;}int main(){int a[8]={2,-3,-5,4,1,7,1,-5};cout<<"最大子段和为:"<<MaxSum(a,8);return 0;}运行结果4、凸多边形最优三角剖分#include<iostream>#include<cmath>#include<cstdlib>#define N 50using namespace std;struct point{int x;int y;};int distance(point X, point Y)//两点距离{int dis = (Y.x-X.x)*(Y.x-X.x) + (Y.y-X.y)*(Y.y-X.y);return (int)sqrt(dis);}int w(point a, point b, point c)//权值{return distance(a,b) + distance(b,c) + distance(a,c);}bool JudgeInput()//判断是否能构成凸多边形{point *v; //记录凸多边形各顶点坐标int *total; //记录坐标在直线方程中的值int m,a,b,c;cout<<"请输入凸多边形顶点个数:";cin>>m;int M = m-1;for(int i=0 ; i<m ; i++){cout<<"输入顶点v"<<i<<"的坐标:";cin>>v[i].x>>v[i].y;}//根据顶点坐标判断是否能构成一个凸多边形for(int j=0 ; j<m ; j++){int p = 0;int q = 0;if(m-1 == j){a = v[m-1].y - v[0].y;b = v[m-1].x - v[0].y;c = b * v[m-1].y - a *v[m-1].x;}else{a = v[j].y - v[j+1].y;b = v[j].x - v[j+1].x;c = b * v[j].y - a * v[j].x;}for(int k=0 ; k<m ; k++){total[k] = a * v[k].x - b * v[k].y + c;if(total[k] > 0){p = p+1;}else if(total[k] < 0){q = q+1;}}if((p>0 && q>0) || (p==0 &&q==0)){cout<<"无法构成凸多边形!"<<endl;exit(1);}}}bool minWeightTriangulation()//计算最优值算法{int M;int **t, **s;point *v;for(int i=1 ; i<=M ; i++)t[i][i] = 0;for(int r=2 ; r<=M ; r++)for(int i=1 ; i<=M-r+1 ; i++){int j = i+r-1;t[i][j] = t[i+1][j] +w(v[i-1],v[i],v[j]);s[i][j] = i;for(int k=i+1 ; k<i+r-1 ; k++){int u = t[i][k] +t[k+1][j] + w(v[i-1],v[k],v[j]);if(u < t[i][j]){t[i][j] = u;s[i][j] = k;}}}return true;}void Traceback(int i, int j, int **s){if(i == j)return;Traceback(i,s[i][j],s);Traceback(s[i][j]+1,j,s);cout<<"三角形:v"<<i-1<<"v"<<s[i][j]<<"v"<<j<<endl; }int main(){int **s; //记录最优三角剖分中所有三角形信息int **t; //记录最优三角剖分所对应的权函数值point *v; //记录凸多边形各顶点坐标int *total; //记录坐标在直线方程中的值int M=0;t = new int *[N];s = new int *[N];for(int i=0 ; i<N ; i++){t[i] = new int[N];s[i] = new int[N];}v = new point[N];total = new int[N];if(JudgeInput()){if(minWeightTriangulation()){Traceback(1,M,s);cout<<endl;cout<<"最优权值之和为:"<<t[1][M]<<endl;}}return 0;}运行结果:5、流水作业调度#include<iostream>#define N 100using namespace std;class Jobtype{public:/* int operator<=(Jobtype a)const{return(key<=a.key);}*/int key;int index;bool job;};void sort(Jobtype *d,int n){int i,j;Jobtype temp;bool exchange; //交换标志for(i = 0;i < n;i ++){ //最多做n-1趟排序exchange = false; //本趟排序开始前,交换标志应为假for(j = n - 1;j >= i;j --)if(d[j+1].key < d[j].key){temp = d[j+1];d[j+1] = d[j];d[j] = temp;exchange=true; //发生了交换,故将交换标志置为真}if(!exchange) //本趟排序未发生交换,提前终止算法return;}}int FlowShop(int n,int *a,int *b,int *c) {Jobtype *d = new Jobtype[n];for(int i=0;i<n;i++)//初始化{d[i].key=a[i]>b[i]?b[i]:a[i];// 执行时间d[i].job=a[i]<=b[i];// 作业组d[i].index=i;//作业序号}sort(d,n);;int j=0;int k=n-1;for(int i=0;i<n;i++)//最优调度{if(d[i].job){c[j++]=d[i].index;}else{c[k--]=d[i].index;}}j=a[c[0]];k=j+b[c[0]];for(int i=1;i<n;i++){j+=a[c[i]];k=j<k?k+b[c[i]]:j+b[c[i]];}delete d;//回收空间return k;//返回调度时间}int main(){int n,*a,*b,*c;cout<<"作业数:";cin>>n;Jobtype *d = new Jobtype[N];a=new int[N];b=new int[N];c=new int[N];cout<<"请输入作业号和时间:";for(int i=0;i<n;i++){cin>>d[i].index>>d[i].key;}cout << endl;int k=FlowShop(n,a,b,c);cout<<"\n调度时间:"<<k<<endl;cout<<"最优调度序列:";for (int i = 0; i < n; i++) // 输出最优调度序列{cout << c[i] << " ";}return 0;}运行结果:6、0-1背包问题#include <iostream>#include <iomanip>using namespace std;const int C=10;//容量const int N=5;//个数int max(const int a,const int b){return a>b?a:b;}int min(const int a,const int b){return a<b?a:b;}/*m为记录数组m[i][j]代表在剩有j容量的条件下,从i开始往后的物品中可以取得的最大价值w为重量数组,v为价值数组n为物品个数,c为开始容量则m[1][c]即此背包能剩下的最大价值*/void knapsack(int **m,int n, int c,int *w, int *v){int jMax = min(w[n]-1,c);//前n-1个物品for(int j=0;j<=jMax;j++)m[n][j]=0;for(int j=w[n];j<=c;j++)m[n][j]=v[n];for(int i=n-1;i>1;i--){jMax=min(w[i]-1,c);for(int j=0;j<=jMax;j++)m[i][j] = m[i+1][j];for(int j=w[i];j<=c;j++)m[i][j] = max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[1][c]=m[2][c];if(c>=w[1])m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]);}//找出最优解,0表示不能装,1表示能装void traceback(int **m,int n,int c,int *x,int *w){for(int i=1;i<n;i++){if(m[i][c]==m[i+1][c]) x[i]=0;else{x[i]=1;c-=w[i];}}x[n]=(m[n][c]==0)?0:1;}int main(){int *v=new int[N+1];int *w=new int[N+1];int **m=new int* [N+1];int *x=new int [N+1];for(int i=0;i<N+1;i++){m[i]=new int[C+1];}cout<<"输入重量序列,"<<N<<"个"<<endl;for(int i=1;i<=N;i++)cin>>w[i];cout<<"输入价值序列,"<<N<<"个"<<endl;for(int i=1;i<=N;i++)cin>>v[i];knapsack(m,N,C,w,v);traceback(m,N,C,x,w);cout<<"最优值:"<<m[1][C]<<endl;cout<<"是否装入背包的情况:";for(int i=1;i<=N;i++){cout<<x[i];}for(int i=0;i<N+1;i++){delete m[i];}delete []m;return 0;}运行结果7、最优二叉搜索树#include<iostream>#include<cmath>#include<limits>#define N 100using namespace std;const double MAX =numeric_limits<double>::max(); //double 的最大值//a[i]为结点i被访问的概率//b[i]为“虚结点”i被访问的概率//m[i][j]用来存放子树(i,j)的期望代价//w[i][j]用来存放子树(i,j)的所有结点(包括虚结点)的a,b概率之和//s[i][j]用来跟踪root的void OptimalBinarySearchTree(double *a,double *b,int n){int s[N][N];double m[N][N];double w[N][N];int i,j,l,r;for(i=1; i<=n+1; i++){m[i][i-1] = b[i-1];w[i][i-1] = b[i-1];}for(l=1; l<=n; l++){for(i=1; i<=n-l+1; i++){j = l+i-1;m[i][j] = MAX;w[i][j] = w[i][j-1] + a[j]+b[j];for(r=i; r<=j; r++){double k = m[i][r-1] + w[i][j] + m[r+1][j];if(k<m[i][j]){m[i][j] = k;s[i][j] = k;}}}}cout<<m[1][n];}int main(){double a[N],b[N];int n;double sum = 0;int i,j,l;cout<<"请输入关键字的个数:"<<endl;cin>>n;cout<<"请输入每个关键字的概率:"<<endl;for(i=1; i<=n; i++){cin>>a[i];sum += a[i];}cout<<"请输入每个虚拟键的概率:"<<endl;for(i=0; i<=n; i++){cin>>b[i];sum += b[i];}if(abs(sum-1)>0.01){cout<<"输入的概率和不为1,请重新输入"<<endl;}cout<<"最优二叉查找树的期望搜索代价为:";OptimalBinarySearchTree(a,b,n);return 0;}运行结果:实验总结通过实现动态规划的这个题目,对动态规划算法有了进一步的了解。

动态规划算法在任务调度中的应用

动态规划算法在任务调度中的应用

动态规划算法在任务调度中的应用随着科技的不断发展和进步,现代社会需要处理和完成的任务也越来越多。

为了提高效率、优化资源,人们需要对这些任务进行科学合理的调度。

而动态规划算法,正是一种在这方面被广泛应用的算法。

动态规划算法是一种基于分治思想的算法,通过将问题分解为子问题的方式,从而达到优化解决问题的效果。

它将问题分成多个子问题,对每个子问题均采用递归的方式进行求解,然后将子问题的解组合成最终的解。

在任务调度中,动态规划算法可以用来确定每项任务的完成时间、资源分配等。

它可以针对不同的任务情况设置不同的约束条件,通过优化不同的目标函数,达到更好的调度效果。

以下是动态规划算法在任务调度中的两个典型应用案例:1. 多机调度问题在多机调度问题中,需要将多个任务分配给不同的机器,并按照机器的加工速度和任务的处理时间,进行合理分配。

该问题通常采用动态规划算法进行求解,最终得到每个任务的完成时间和资源分配情况。

多机调度问题的求解思路是,先将整个调度问题分解成多个单机调度的子问题,再对每个子问题采用动态规划算法进行求解。

最终,将每个子问题的最优解组合成整体的最优解。

在求解多机调度问题时,动态规划算法的核心是贪心算法。

贪心算法指的是,优先考虑当前最优的解决方案,而不是考虑是否存在更好的解决方案。

因此,每个任务的处理时间和临近任务的时间关系,以及机器的处理速度等因素,均需要考虑其中。

2. 总收益最大化问题在总收益最大化问题中,需要将受理的任务分配给不同的执行人员。

执行人员的工作效率不同,同时还存在成本和资源限制。

因此,最终需要确定每个任务的分配方案,以及分配给不同执行人员的任务数量和执行时间。

总收益最大化问题的求解思路是,将任务分解为多个子问题,分别对每个子问题进行求解,然后将每个子问题的最优解组合成整体的最优解。

其中,采用了动态规划算法和线性规划算法等技术,通过数学模型的建立和求解,最终得到调度方案及其最终效益。

总收益最大化问题的求解涉及到非常复杂的约束条件与目标函数,因此需要运用较高级的数学模型和算法方法。

动态规划实验报告摘要(3篇)

动态规划实验报告摘要(3篇)

第1篇本实验报告针对动态规划算法进行深入研究和实践,旨在通过一系列实验,加深对动态规划思想、基本原理及实际应用的理解。

实验内容涵盖了动态规划算法的多个经典问题,包括找零钱问题、独立任务最优调度问题、最长公共子序列问题、矩阵连乘问题、剪绳子问题以及0-1背包问题等。

一、实验目的1. 理解动态规划算法的概念,掌握动态规划的基本思想和解决问题的基本步骤。

2. 学习动态规划算法设计策略,提高算法设计能力。

3. 通过实际案例,体会动态规划算法在解决实际问题中的应用价值。

二、实验内容与步骤1. 找零钱问题实验要求设计一个动态规划算法,对给定面值的硬币组合,计算出所有可能找零方式的硬币个数。

通过实验,掌握了动态规划算法的基本原理,并熟悉了动态规划在解决组合优化问题中的应用。

2. 独立任务最优调度问题实验要求设计一个动态规划算法,使得两台处理机处理完n个作业的时间最短。

通过实验,了解了动态规划在解决调度问题中的应用,并掌握了多阶段决策问题的求解方法。

3. 最长公共子序列问题实验要求找出两个序列的最长公共子序列。

通过实验,学习了动态规划在解决序列匹配问题中的应用,并掌握了如何通过动态规划算法优化问题求解过程。

4. 矩阵连乘问题实验要求确定计算矩阵连乘积的计算次序,使得所需数乘次数最少。

通过实验,了解了动态规划在解决矩阵连乘问题中的应用,并掌握了如何通过动态规划算法优化计算过程。

5. 剪绳子问题实验要求将一根绳子剪成m段,使得各段乘积最大。

通过实验,掌握了动态规划在解决资源分配问题中的应用,并学会了如何通过动态规划算法找到最优解。

6. 0-1背包问题实验要求用动态规划算法解决0-1背包问题。

通过实验,了解了动态规划在解决背包问题中的应用,并掌握了如何通过动态规划算法优化问题求解过程。

三、实验结果与分析通过对以上问题的动态规划算法实现,实验结果表明:1. 动态规划算法能够有效地解决组合优化问题、调度问题、序列匹配问题、矩阵连乘问题、资源分配问题以及背包问题等。

作业调度实验报告

作业调度实验报告

作业调度实验报告作业调度实验报告引言:作业调度是计算机操作系统中的一个重要概念,它涉及到如何合理地安排和管理计算机系统中的各个作业的执行顺序,以提高计算机系统的效率和资源利用率。

本实验旨在通过模拟不同的作业调度算法,探究它们在不同场景下的性能表现。

实验目的:1. 了解作业调度的基本概念和原理;2. 掌握作业调度算法的实现方法;3. 分析不同作业调度算法在不同场景下的优缺点。

实验过程:1. 实验环境的搭建在实验开始前,我们需要搭建一个适合进行作业调度实验的环境。

我们选择了一台配置较高的计算机,并安装了操作系统和相关的开发工具。

2. 实验数据的准备为了模拟真实的作业调度场景,我们需要准备一些作业数据。

这些数据包括作业的到达时间、执行时间、优先级等信息。

我们通过编写程序生成了一批随机的作业数据,并将其保存在文件中。

3. 实验算法的实现根据实验要求,我们实现了三种常见的作业调度算法:先来先服务(FCFS)、最短作业优先(SJF)和优先级调度算法(Priority Scheduling)。

我们使用C语言编写了相应的代码,并对其进行了测试和调试。

4. 实验结果的分析我们将不同作业调度算法在相同作业数据下的运行结果进行了比较和分析。

通过观察和统计,我们得到了各个算法的平均周转时间、平均等待时间等性能指标。

同时,我们还通过绘制图表的方式直观地展示了这些数据。

实验结果与讨论:1. 先来先服务算法(FCFS)先来先服务算法是最简单的作业调度算法之一,它按照作业到达的顺序依次执行。

在实验中,我们发现该算法对于短作业来说表现较好,但对于长作业来说会导致平均等待时间较长。

2. 最短作业优先算法(SJF)最短作业优先算法是一种非抢占式的调度算法,它优先执行执行时间最短的作业。

在实验中,我们发现该算法能够有效减少平均等待时间,但对于长作业来说可能会导致饥饿现象。

3. 优先级调度算法(Priority Scheduling)优先级调度算法根据作业的优先级来安排执行顺序。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

动态规划-流水作业调度报告C1 问题描述和分析N个作业{1,2,………,n}要在由两台机器M1和M2组成的流水线上完成加工。

每个作业加工的顺序都是先在M1上加工,然后在M2上加工。

M1和M2加工作业i所需的时间分别为ai和bi,1≤i≤n。

流水作业高度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少。

设全部作业的集合为N={1,2,…,n}, S⊆N,,一般情况下,机器M1开始加工作业S时,机器M2还在加工其他作业,要等时间t后才可利用.将这种情况下完成S中作业所需的最短时间记为T(S,t).流水作业调度的最优值为T(N,0)即,设π是所给n个流水作业的一个最优调度,它所需的加工时间为a(π1)+T’.其中T’是在此机器M2的等待时间为b(π1)时,安排作业π1, π2,…πn所需时间.所以S=N-{π1},有T’=T(S,b(π1)).由T的定义知T’≥T(S,b(π1)).若T’>T(S,b(π1)),设π’是作业集S在机器M2的等待时间为b(π1)情况下的一个最优调度.则π1, π’2,…, π’n是N的一个调度,且该调度所需的时间为a(π1)+T(S,b(π1))<a(π1)+T’.这与π是N的最优调度矛盾.故T’≤T(S,b(π1).从而T’=T(S,b(π1).即当机器M1为空闲即未安排任何加工任务时,则任何一个作业的第一个任务(第一道工序)都可以立即在M1上执行,无须任何先决条件。

因此容易知道,必有一个最优调度使得在M1上的加工是无间断的。

实际上,如某个最优调度π在M1上安排的加工是有间断的,则我们可以把所有在M1上出现间断处的任务的开始加工时间提前,使得在M1上的加工是无间断的;而在M2上仍按π原先的安排。

把这样调整之后的调度记作为π’。

由于在调度π’下,任何一个任务在M1上加工的结束时间不晚于在调度π下的结束时间,故调度π’不会影响在M2上进行加工的任何一个任务的开始时间。

由于调度π’在M1上的结束时间早于调度π,在M2上的结束时间与调度π相同,而π又是最优调度,所以π’也是最优调度。

由此我们得到:一定有一个最优调度使得在M1上的加工是无间断的。

另外,也一定有一个最优调度使得在M2上的加工空闲时间(从O时刻起算)为最小,同时还满足在M1上的加工是无间断的。

(证明留作作业)因此,如果我们的目标是只需找出一个最优调度,我们可以考虑找:在M1上的加工是无间断的、同时使M2的空闲时间为最小的最优调度。

(根据上述理由,这样的最优调度一定存在。

)可以证明,若在M2上的加工次序与在M1上的加工次序不同,则只可能增加加工时间(在最好情况下,增加的时间为O)。

也就是说,在M1上的加工次序已确定的情况下,至少有一个最优调度,其在M1上的加工次序与在M2上的加工次序是完全相同的。

因此,当只需找到一个最优调度时,我们仅需要考虑在和M1和M2上加工次序完全相同的调度。

以下的讨论均以此为前提。

为简化起见,我们假定所有ai≠0。

因为如果有ai=0的作业,我们可以先对所有ai≠0的作业进行调度,然后把所有ai=0的作业放到最前面执行(可按任意次序)。

最优调度具有如下性质:在所确定的最优调度的排列中去掉第一个执行作业后,剩下的作业排列仍然还是一个最优调度,即该问题具有最优子结构的性质。

而且,在计算规模为n的作业集合的最优调度时,该作业集合的子集合的最优调度会被多次用到,即该问题亦具有高度重复性。

这就引导我们考虑用动态规划法求解C2 算法设计递归计算最优值由流水作业调度问题的最优子结构性质可知,T(N,0)=min{ai+T(N-{i},bi)},其中1≤i≤n推到一般情形下便有T(S,t)=min{ai+T(S-{i},bi+max{t-ai,0})}其中,max{t-ai,0}这一项是由于在机器M2上,作业i须在max{t,ai}时间之后才能开工.因此,在机器M1上完成作业i之后,在机器上还需要bi+max{t,ai}-ai=bi+max{t-ai,0}时间才能完成对作业i加工.而需要对算法作一定的改进。

设π是作业子集S的某一个调度,该调度首先安排作业i,其次安排作业j, M2需等待t个时间单位以后才可以用于S中的作业加工。

记t’=bi+max{t-ai,0},则由(*)式调度π的g(S,t)可写为 g(S,t)=ai+ g(S-{i}, t’)= ai+ aj+ g(S-{i,j}, bj+max{t’-aj,0})。

由于x+ max{y1, y2,⋯,yn}= max{x+y1,x+y2,⋯,x+yn},,t’= bi+m ax{t-ai,0},所以bj+max{t’-aj,0}= bj+max{bi+max{t-ai,0}-aj, 0}= bj+bi - aj+max{max{t-ai,0},aj-bi} =bj+ bi - aj +max{t-ai, 0, aj-bi} =bj+ bi - aj - ai +max{t, ai, ai+aj-bi}。

记tij= bj+ bi - aj - ai +max{t, ai, ai+aj-bi}(= bj+max{t’-aj,0}),则调度π的g(S,t)=ai+ aj+ g(S-{i,j}, tij)。

将调度π中的作业i与j的加工次序交换(其它加工次序不变)所得调度记为π’,则调度π’的最早完工时间g’(S,t)=ai+ aj+g(S-{i,j}, tji)。

显然,若tij ≤ tji,则有g(S,t) ≤g’(S,t)即i在前j在后的安排用时较少;反之,若tij >tji,则j在前i在后的安排用时较少。

因此,我们要找出判断tij与tji之间的大小关系的表达式。

由于tij-tji= max{t, ai,ai+aj-bi}- max{t, aj, ai+aj-bj},故我们只要比较 max{t, ai, ai+aj-bi}与max{t, aj, ai+aj-bj}的大小就可以了, 即tij ≤ tji当且仅当max{t, ai, ai+aj-bi} ≤ max{t, aj, ai+aj-bj}。

由于max{t, ai, ai+aj-bi} ≤ max{t, aj, ai+aj-bj} 对任何t ≥ 0成立,当且仅当 max{ai, ai+aj-bi} ≤ max{aj, ai+aj-bj}成立,当且仅当 ai+aj+max{-aj, -bi} ≤ ai+aj+max{-ai, -bj}成立,当且仅当 max{-aj, -bi} ≤ max{-ai, -bj}成立,当且仅当 min{aj, bi} ≥ min{ai, bj}成立。

即当min{ ai , aj , bi , bj}为ai或者bj时,Johnson 不等式成立,此时把i排在前j排在后的调度用时较少;反之,若min{ ai , aj , bi , bj}为aj或者bi时,则j排在前i排在后的调度用时较少。

将此情况推广到一般。

当min{ a1, a2,┅, an , b1, b2,┅, bn }=ak时,则对任何i≠k,都有min{ai, bk} ≥ min{ak, bi}成立,故此时应将作业k安排在最前面,作为最优调度的第一个执行的作业;当min{ a1, a2,┅, an , b1, b2,┅, bn }= bk时,则对任何i≠k,也都有min{ak, bi}≥min{ai, bk}成立,故此时应将作业k安排在最后面,作为最优调度的最后一个执行的作业。

C 4 程序实现主要程序class Jobtype{public:int operator<=(Jobtype a) const{ return (key<=a.key);}int key;int index;bool job;};int FlowShop(int n,int a[],int b[],int c[]){Jobtype *d=new Jobtype[n];for(int i=0;i<n;i++){d[i].key=a[i]>b[i]?b[i]:a[i];d[i].job=a[i]<=b[i];d[i].index=i;}MergeSort(d,n);//对n个作业进行排序int j=0,k=n-1;for(i=0;i<n;i++){if(d[i].job) c[j++]=d[i].index;//选定作业的加工顺序 else c[k--]=d[i].index;}//记住进行加工作业所用的时间j,kj=a[c[0]];k=j+b[c[0]];for(i=1;i<n;i++){j+=a[c[i]];k=j<k?k+b[c[i]]:j+b[c[i]];}cout<<"最优加工顺序"<<endl;for(int g=0;g<n;g++){cout<<g+1<<"["<<a[c[g]]<<","<<b[c[g]]<<"]"<<" ";} cout<<endl;//输出最优加工顺序cout<<"最优调度所用的时间"<<endl;cout<<k<<endl;//输出最优调度所用的时间delete d;return k;}void main(){int c[20];int n;int *a,*b;ifstream fin("data.txt");fin>>n;make1darray(a,n+1);make1darray(b,n+1);for(int i=0;i<n;i++){ fin>>a[i]>>b[i];}cout<<"原来的加工顺序"<<endl;for(i=0;i<n;i++){cout<<i+1<<"["<<a[i]<<","<<b[i]<<"]"<<" ";}cout<<endl;FlowShop(n,a,b,c);}C5算法复杂性分析由于合并排序需要O(nlogn)时间,对数组a[n],b[n],c[n]进行初始化都是用了O(n)本程序, 下标变量初始化:i←0;j←0;k←n-1;是O(1), 主要有3个循环语句而且用时是都是O(n), ∴算法的时间复杂度为O(nlogn)。

相关文档
最新文档