算法作业5

5.1 代码如下: 5.1代码如下: 5.1代码如下:

#include<iostream>
using namespace std;

int n=3;
int x[3]={1,1,1};
 
void show(int a[]) 
{
	for(int i=0;i<n;i++)
		cout<<a[i]<<"\t";
	cout<<endl<<endl;
}
 
//约束条件
bool P(int x[],int i)//表示第几层 
{
	switch(i)
	{
	case 0: 
		if(3*x[0]<=12)return true;
			else return false;
	case 1:
		if(3*x[0]+4*x[1]<=12)return true;
			else return false;
	case 2:
		if(3*x[0]+4*x[1]+2x[2]<=12)return true;
			else return false;
	}
	
} 
 
void fun(int i)
{
//	cout<<i<<"c"<<endl;
//	show(x);
	if(i>n-1)//已经结束了最后一个数 
	{
//		cout<<"结果:";
		show(x);
		return;//结束最后一层,回溯到上一层 
	}
	//若不变 
	if(P(x,i)&&x[i]<4)//符合约束条件 
	{
		x[i]=1;
		fun(i+1); //下一层 
	}
	//若2
	if(P(x,i)&&x[i]<4)//符合约束条件 
	{
		int t=x[i];
		x[i]=2;
		fun(i+1); //下一层 
		x[i]=t;//回复 
	}
	
	//若3
	if(P(x,i)&&x[i]<4)//符合约束条件 
	{
		int t=x[i];
		x[i]=3; 
		fun(i+1); //下一层 
		x[i]=t;//回溯后,本层尝试下一个可能 
	} 
}
 
int main()
{
	fun(0);
	return 0;
} 

解分别为: ( 0 , 0 , 0 ) , ( 0 , 0 , 1 ) , ( 0 , 0 , 2 ) , ( 0 , 0 , 3 ) , ( 0 , 0 , 4 ) , ( 0 , 0 , 5 ) , ( 0 , 0 , 6 ) , 解分别为:(0,0,0), (0,0,1), (0,0,2), (0,0,3), (0,0,4), (0,0,5), (0,0,6), 解分别为:(0,0,0),(0,0,1),(0,0,2),(0,0,3),(0,0,4),(0,0,5),(0,0,6),
( 0 , 1 , 0 ) , ( 0 , 1 , 1 ) , ( 0 , 1 , 2 ) , ( 0 , 1 , 3 ) , ( 0 , 1 , 4 ) , ( 0 , 2 , 0 ) , ( 0 , 2 , 1 ) , (0,1,0), (0,1,1), (0,1,2), (0,1,3), (0,1,4), (0,2,0), (0,2,1), (0,1,0),(0,1,1),(0,1,2),(0,1,3),(0,1,4),(0,2,0),(0,2,1),
( 0 , 2 , 2 ) , ( 0 , 3 , 0 ) , ( 1 , 0 , 0 ) , ( 1 , 0 , 1 ) , ( 1 , 0 , 2 ) , ( 1 , 0 , 3 ) , ( 1 , 0 , 4 ) , (0,2,2), (0,3,0), (1,0,0), (1,0,1), (1,0,2), (1,0,3), (1,0,4), (0,2,2),(0,3,0),(1,0,0),(1,0,1),(1,0,2),(1,0,3),(1,0,4),
( 1 , 1 , 0 ) , ( 1 , 1 , 1 ) , ( 1 , 1 , 2 ) , ( 1 , 2 , 0 ) , ( 2 , 0 , 0 ) , ( 2 , 0 , 1 ) , ( 2 , 0 , 2 ) , (1,1,0), (1,1,1), (1,1,2), (1,2,0), (2,0,0), (2,0,1), (2,0,2), (1,1,0),(1,1,1),(1,1,2),(1,2,0),(2,0,0),(2,0,1),(2,0,2),
( 2 , 0 , 3 ) , ( 2 , 1 , 0 ) , ( 2 , 1 , 1 ) , ( 3 , 0 , 0 ) , ( 3 , 0 , 1 ) , ( 4 , 0 , 0 ) (2,0,3), (2,1,0), (2,1,1), (3,0,0), (3,0,1), (4,0,0) (2,0,3),(2,1,0),(2,1,1),(3,0,0),(3,0,1),(4,0,0)

5.2 5.2 5.2

#include <iostream>
#include <fstream>
using namespace std;
class Machine
{
public:
	int n_, m_, d_;// n_零件个数,m_供应商个数,d_最大总价格
	int** c_; // c_[i][j]第i个零件第j个供应商得价格
	int** w_; //w_[i][j]第i个零件第j个供应商的重量
	int sumw = 0;//初始化当前已选择的零件的重量
	int sumc = 0;//当前已选择的零件的价格
	int* path;//记录第i个零件选择的供应商
	int minw = INT_MAX; //初始化最小重量
	int *bestpath;//取得最小重量时各供应商得选择

	Machine() // 把初始数据从文件中读出并初始化类
	{
		ifstream infile("input.txt");
		if (!infile)
		{
			cout << "open input.txt error!!\n";
			return;
		}
		infile >> n_ >> m_ >> d_;
		c_ = new int* [n_];
		w_ = new int* [n_];
		path = new int[n_];
		bestpath = new int[n_];
		for (int i = 0; i < n_; i++)
		{
			c_[i] = new int[m_];
			w_[i] = new int[m_];
		}
		for (int i = 0; i < n_; i++)
		{
			for (int j = 0; j < m_; j++)
			{
				infile >> c_[i][j];
			}
		}
		for (int i = 0; i < n_; i++)
		{
			for (int j = 0; j < m_; j++)
			{
				infile >> w_[i][j];
			}
		}
		infile.close();
	}

	~Machine() //析构函数,释放内存
	{
		for (int i = 0; i < n_; i++)
		{
			delete[] c_[i];
			delete[] w_[i];
		}
		delete c_;
		delete w_;
	}
	void Backtracking(int i) //主回溯函数
	{
		if (i >= n_) //递归终止条件
		{
			//重量小于最小重量,更新
			if (sumw < minw)
			{
				for (int i = 0; i < n_; i++)
				{
					bestpath[i] = path[i];
				}
				minw = sumw;
			}
			return;
		}
		else
		{
			for (int j = 0; j < m_; j++) //遍历m个供应商
			{
				sumw += w_[i][j];
				sumc += c_[i][j];
				path[i] = j;
				if (sumw < minw && sumc <= d_)//当前总价格小于最大价格,当前总重量小于最小总重量
				{
					Backtracking(i + 1);
				}
				//回溯
				sumw -= w_[i][j];
				sumc -= c_[i][j];
			}
		}
	}
	void WriteFile()//把结果写入文件
	{
		ofstream out("output.txt");
		out << minw << endl;
		for (int i = 0; i < n_; i++)
		{
			out << bestpath[i] + 1 << " ";
		}
		out.close();
	}
};

int main()
{
	Machine x;
	x.Backtracking(0);
	x.WriteFile();
	return 0;
}

运行上面程序,这 4 种配件应分别选择供货商 3 , 1 , 2 , 3 , 总重量为 31 , 价值为 119. 运行上面程序,这4种配件应分别选择供货商3,1,2,3,总重量为31,价值为119. 运行上面程序,这4种配件应分别选择供货商3,1,2,3,总重量为31,价值为119.

5.3 所有可能的 L a t i n 方有 24 个,如下所示 : 5.3所有可能的Latin方有24个,如下所示: 5.3所有可能的Latin方有24个,如下所示:
在这里插入图片描述

5.6 设 S = { a 1 , a 2 , … , a n } . 求 S 满足条件 ∑ a i ∈ A a i = M 的所有的子集 A . 5.6设S=\lbrace a_{1},a_{2},…,a_{n}\rbrace.求S 满足条件\sum_{a_{i}\in A} a_{i}=M 的所有的子集A. 5.6S={a1,a2,,an}.S满足条件aiAai=M的所有的子集A.
用回溯算法 . 解向量为 < x 1 , x 2 , … , x n > , x i = 0 , 1. 其中 x i = 1 当且仅当 a i ∈ A . 用回溯算法.解向量为<x_{1},x_{2},…,x_{n} >,x_{i}=0,1.其中x_{i}=1当且仅当a_{i}\in A. 用回溯算法.解向量为<x1,x2,,xn>,xi=0,1.其中xi=1当且仅当aiA.
搜索空间为子集树 . 搜索空间为子集树. 搜索空间为子集树.
部分向量 < x 1 , x 2 , … , x k > 表示已经考虑了对 a 1 , a 2 , … , a k 的选择 . 部分向量<x_{1},x_{2},…,x_{k}>表示已经考虑了对a_{1},a_{2},…,a_{k} 的选择. 部分向量<x1,x2,,xk>表示已经考虑了对a1,a2,,ak的选择.
结点分支的约束条件是 : B ( i ) = ∑ i = 1 k a i x i < M 且 a k + 1 ∈ S − { a 1 , a 2 , . . . , a k } 结点分支的约束条件是:B(i)=\sum_{i=1}^{k}a_{i}x_{i}<M 且a_{k+1}\in S-\lbrace a_{1},a_{2},...,a_{k}\rbrace 结点分支的约束条件是:B(i)=i=1kaixi<Mak+1S{a1,a2,...,ak}
最坏情况下算法的时间复杂度是 O ( 2 n ) . 最坏情况下算法的时间复杂度是O(2^{n}). 最坏情况下算法的时间复杂度是O(2n).

5.7 设 n 个人的集合是 { 1 , 2 , … , n } , n 项工作的集合是 { 1 , 2 , … , n } , 每个人恰好 1 项工作 . 5.7设n 个人的集合是\lbrace 1,2,…,n\rbrace,n 项工作的集合是\lbrace 1,2,…,n\rbrace,每个人恰好1项工作. 5.7n个人的集合是{1,2,,n},n项工作的集合是{1,2,,n},每个人恰好1项工作.
x i = j 表示把工作 j 分配给 i , 其中 i , j = 1 , 2 , … , n x_{i}=j表示把工作j分配给i,其中i,j=1,2,…,n xi=j表示把工作j分配给i,其中i,j=1,2,,n
解向量是 X = < x 1 , x 2 , … , x n > , 分配成本是 C ( X ) = ∑ i = 1 k C ( i , x i ) 解向量是X=<x_{1},x_{2},…,x_{n}>,分配成本是C(X)=\sum_{i=1}^{k}C(i,x_{i}) 解向量是X=<x1,x2,,xn>,分配成本是C(X)=i=1kC(i,xi)
搜索空间是排列树 . 搜索空间是排列树. 搜索空间是排列树.
部分向量 < x 1 , x 2 , … , x k > 表示已经考虑了对人 1 , 2 , … , k 的工作分配 部分向量<x_{1},x_{2},…,x_{k}>表示已经考虑了对人1,2,…,k 的工作分配 部分向量<x1,x2,,xk>表示已经考虑了对人1,2,,k的工作分配
结点分支的约束条件是 : x k + 1 ∈ { 1 , 2 , . . . , n } − { x 1 , x 2 , . . . , x n } 结点分支的约束条件是:x_{k+1}\in \lbrace 1,2,...,n\rbrace-\lbrace x_{1},x_{2},...,x_{n}\rbrace 结点分支的约束条件是:xk+1{1,2,...,n}{x1,x2,...,xn}
代价函数: F ( x 1 , x 2 , . . . , x k ) = ∑ i = 1 k C ( i , x i ) + ∑ i = k + 1 n m i n ( C ( i , t ) ∣ t ∈ { 1 , 2 , … , n } − { x 1 , x 2 , . . . , x n } ) 代价函数:F(x_{1},x_{2},...,x_{k})=\sum_{i=1}^{k}C(i,x_{i})+\sum_{i=k+1}^{n}min(C(i,t)|t\in \lbrace 1,2,…,n\rbrace-\lbrace x_{1},x_{2},...,x_{n}\rbrace) 代价函数:F(x1,x2,...,xk)=i=1kC(i,xi)+i=k+1nmin(C(i,t)t{1,2,,n}{x1,x2,...,xn})
界 B 是已得到的最好可行解的分配成本 . 如果代价函数大于界 , 则回溯 . 界B 是已得到的最好可行解的分配成本.如果代价函数大于界,则回溯. B是已得到的最好可行解的分配成本.如果代价函数大于界,则回溯.
算法最坏情况下的时间复杂度是 O ( n n ! ) . 算法最坏情况下的时间复杂度是O(nn!). 算法最坏情况下的时间复杂度是O(nn!).

5.9 设 n 个任务的标号分别为 1 , 2 , … , n , k 个处理器的标号分别为 1 , 2 , … , k . 5.9设n 个任务的标号分别为1,2,…,n,k 个处理器的标号分别为1,2,…,k. 5.9n个任务的标号分别为1,2,,n,k个处理器的标号分别为1,2,,k.
算法主要步骤如下 : 算法主要步骤如下: 算法主要步骤如下:
1. 给出将 n 个任务分到 k 个处理器上的分配方法 . 1.给出将n 个任务分到k 个处理器上的分配方法. 1.给出将n个任务分到k个处理器上的分配方法.
2. 在每个分配方法下 , 算出每个处理器上所分配到的任务的执行时间 , 并求这些执行时间的最大值 , 该最大值即为这个分配方法的执行时间 . 2.在每个分配方法下,算出每个处理器上所分配到的任务的执行时间,并求这些执行时间的最大值,该最大值即为这个分配方法的执行时间. 2.在每个分配方法下,算出每个处理器上所分配到的任务的执行时间,并求这些执行时间的最大值,该最大值即为这个分配方法的执行时间.
3. 求出所有分配方法的执行时间的最小值 . 3.求出所有分配方法的执行时间的最小值. 3.求出所有分配方法的执行时间的最小值.
步骤 1 可以用深度优先策略遍历的 k 元完全正则树实现 , 得到 k n 个分配方案 . 步骤1可以用深度优先策略遍历的k元完全正则树实现,得到k^{n}个分配方案. 步骤1可以用深度优先策略遍历的k元完全正则树实现,得到kn个分配方案.
步骤 2 : 在分配方案 < i 1 , i 2 , … , i n > 下 , 如 i k = i l , 则表明任务 k 和 l 被分配到同一个处理器 i k 上执行 . 步骤2:在分配方案<i_{1},i_{2},…,i_{n} >下,如i_{k}=i_{l},则表明任务k和l被分配到同一个处理器i_{k}上执行. 步骤2:在分配方案<i1,i2,,in>,ik=il,则表明任务kl被分配到同一个处理器ik上执行.
遍历序列 i 1 , i 2 , … , i n , 找到每个处理器上分配到的所有任务 w 1 , w 2 , … , w u , 则在这个分配方案下 , 遍历序列i_{1},i_{2},…,i_{n},找到每个处理器上分配到的所有任务 w_{1},w_{2},…,w_{u},则在这个分配方案下, 遍历序列i1,i2,,in,找到每个处理器上分配到的所有任务w1,w2,,wu,则在这个分配方案下,
该处理器的执行时间为 t w 1 + t w 2 + … + t w u . 再在所有处理器的执行时间中求出最大值 , 该处理器的执行时间为t_{w_{1}} +t_{w_{2}} +…+t_{w_{u}} .再在所有处理器的执行时间中求出最大值, 该处理器的执行时间为tw1+tw2++twu.再在所有处理器的执行时间中求出最大值,
则该最大值即为分配方案 < i 1 , i 2 , … , i n > 的执行时间 . 该步骤的执行时间是 O ( n k n ) . 则该最大值即为分配方案<i_{1},i_{2},…,i_{n} >的执行时间.该步骤的执行时间是O(nk^{n}). 则该最大值即为分配方案<i1,i2,,in>的执行时间.该步骤的执行时间是O(nkn).
步骤 3 是在 k n 个分配方案的执行时间中求最小值 , 执行时间是 O ( k n ) . 步骤3是在kn 个分配方案的执行时间中求最小值,执行时间是O(kn ). 步骤3是在kn个分配方案的执行时间中求最小值,执行时间是O(kn).
所以,算法执行时间是 O ( n k n ) . 所以,算法执行时间是O(nk^{n} ). 所以,算法执行时间是O(nkn).

5.11 用 X [ i . j ] 表示该 m ∗ n 的 0 − 1 矩阵 , X [ i , j ] = 1 当且仅当陈列室 ( i , j ) 有哨兵 . 5.11用X[i.j]表示该m*n的0-1矩阵,X[i,j]=1当且仅当陈列室(i,j) 有哨兵. 5.11X[i.j]表示该mn01矩阵,X[i,j]=1当且仅当陈列室(i,j)有哨兵.
初始令所有的 X [ i , j ] = 1 , i = 1 , 2 , … , m , j = 1 , 2 , … , n . 初始令所有的 X[i,j]=1,i=1,2,…,m,j=1,2,…,n. 初始令所有的X[i,j]=1,i=1,2,,m,j=1,2,,n.
算法从 ( 1 , 1 ) 开始直到 ( m , n ) 为止 , 搜索树是二叉树 , 有 m ∗ n 层 . 算法从(1,1)开始直到(m,n)为止,搜索树是二叉树,有m*n层. 算法从(1,1)开始直到(m,n)为止,搜索树是二叉树,mn.
如果令 X [ i , j ] = 0 , 则取消 ( i , j ) 位置的哨兵 , 进入左子树 ; 否则 , 进入右子树 . 如果令X[i,j]=0,则取消(i,j)位置的哨兵,进入左子树;否则,进入右子树. 如果令X[i,j]=0,则取消(i,j)位置的哨兵,进入左子树;否则,进入右子树.
在进入左子树时 , 需要检查房间被监视的情况 . 在进入左子树时,需要检查房间被监视的情况. 在进入左子树时,需要检查房间被监视的情况.
即当取消 ( i , j ) 位置的哨兵时 , 此位置及其上、下、左、右位置是否被监视 . 如果有不被监测的情况出现 , 则该分支不再搜索 . 即当取消(i,j)位置的哨兵时,此位置及其上、下、左、右位置是否被监视.如果有不被监测的情况出现,则该分支不再搜索. 即当取消(i,j)位置的哨兵时,此位置及其上、下、左、右位置是否被监视.如果有不被监测的情况出现,则该分支不再搜索.
最坏情况下的时间复杂度是 O ( 2 n m ) . 最坏情况下的时间复杂度是O(2^{nm}). 最坏情况下的时间复杂度是O(2nm).
X[i,j]=1,i=1,2,…,m,j=1,2,…,n.$
算法从 ( 1 , 1 ) 开始直到 ( m , n ) 为止 , 搜索树是二叉树 , 有 m ∗ n 层 . 算法从(1,1)开始直到(m,n)为止,搜索树是二叉树,有m*n层. 算法从(1,1)开始直到(m,n)为止,搜索树是二叉树,mn.
如果令 X [ i , j ] = 0 , 则取消 ( i , j ) 位置的哨兵 , 进入左子树 ; 否则 , 进入右子树 . 如果令X[i,j]=0,则取消(i,j)位置的哨兵,进入左子树;否则,进入右子树. 如果令X[i,j]=0,则取消(i,j)位置的哨兵,进入左子树;否则,进入右子树.
在进入左子树时 , 需要检查房间被监视的情况 . 在进入左子树时,需要检查房间被监视的情况. 在进入左子树时,需要检查房间被监视的情况.
即当取消 ( i , j ) 位置的哨兵时 , 此位置及其上、下、左、右位置是否被监视 . 如果有不被监测的情况出现 , 则该分支不再搜索 . 即当取消(i,j)位置的哨兵时,此位置及其上、下、左、右位置是否被监视.如果有不被监测的情况出现,则该分支不再搜索. 即当取消(i,j)位置的哨兵时,此位置及其上、下、左、右位置是否被监视.如果有不被监测的情况出现,则该分支不再搜索.
最坏情况下的时间复杂度是 O ( 2 n m ) . 最坏情况下的时间复杂度是O(2^{nm}). 最坏情况下的时间复杂度是O(2nm).

  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值