用动态规划法解决最大子段和问题
二、实验目的:
课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的:
(1)使学生掌握动态规划法思想
(2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法;
(3)使学生提高对实际问题的分析、设计和实现能力;
(4)为学生后续课程的学习及课程设计打下坚实的实践基础。
三、使用的策略:
动态规划法思想
四、实验内容:
(一) 问题描述
给定由n个整数(可能为负整数)组成的序列a1,a2,a3,···,an,求该序列的子段和的最大值。当所有整数均为负整数是定义其最大子段和为0,一次定义,所求的最优质值为:max{0、max子段和}。
(二) 算法描述
动态规划法的基本思想:
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。
算法设计:
#include "stdafx.h"
int MaxSum(int a[],int n,int &Start,int&End){
intsum=0;
int*b,t;
b=newint[n+1];
b[0]=0;
for(inti=1;i<=n;i++){
if(b[i-1]>0){
b[i]=b[i-1]+a[i];
}
else {
b[i]=a[i];t=i;
}
if(b[i]>sum){
sum=b[i];
Start=t;
End=i;
}
}
delete[]b;
returnsum;
}
int main(int argc, char* argv[])
{
inta[7]={0,-2,11,-4,13,-5,-2},sum,Start,End,i;
sum=MaxSum(a,6,Start,End);
for(i=Start;i<=End;i++){
printf("%d ",a[i]);
}
printf("\n%d\n",sum);
getchar();
getchar();
return0;
}
用分支界限法解决最大子段和问题
二、实验目的:
课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的:
(1)使学生掌握分支界限法思想
(2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法;
(3)使学生提高对实际问题的分析、设计和实现能力;
(4)为学生后续课程的学习及课程设计打下坚实的实践基础。
三、使用的策略:
分支界限法
四、实验内容:
(一) 问题描述
在下图所给的有向图G中,每一边都有一个非负边权。要求图G的从源顶点s到目标顶点t之间的最短路径。
(二) 算法描述
分支界限法的基本思想:
分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。
在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。
此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。
算法设计:
#include
#include
#include
#include
using namespacestd;
struct node_info
{
public:
node_info (int i,int w)
: index (i), weight (w) {}
node_info ()
: index(0),weight(0) {}
node_info (const node_info & ni)
: index (ni.index), weight (ni.weight){}
friend
bool operator < (const node_info<h,const node_info& rth) {
return lth.weight > rth.weight ; // 为了实现从小到大的顺序
}
public:
int index; // 结点位置
int weight; // 权值
};
struct path_info
{
public:
path_info ()
: front_index(0), weight(numeric_limits
public:
int front_index;
int weight;
};
// single sourceshortest paths
classss_shortest_paths
{
public:
ss_shortest_paths (constvector
:no_edge (-1), end_node (end_location),node_count (g.size()) , graph (g)
{}
// 打印最短路径
void print_spaths () const {
cout << "min weight : "<< shortest_path << endl;
cout << "path: " ;
copy(s_path_index.rbegin(),s_path_index.rend(),
ostream_iterator
cout << endl;
}
// 求最短路径
void shortest_paths () {
vector
priority_queue
min_heap.push (node_info(0,0)); // 将起始结点入队
while (true) {
node_info top = min_heap.top(); // 取出最大值
min_heap.pop ();
// 已到达目的结点
if (top.index == end_node) {
break ;
}
// 未到达则遍历
for (int i = 0; i < node_count;++ i) {
// 顶点top.index和i间有边,且此路径长小于原先从原点到i的路径长
if (graph[top.index][i] !=no_edge &&
(top.weight +graph[top.index][i]) < path[i].weight) {
min_heap.push (node_info(i,top.weight + graph[top.index][i]));
path[i].front_index =top.index;
path[i].weight = top.weight+ graph[top.index][i];
}
}
if (min_heap.empty()) {
break ;
}
}
shortest_path = path[end_node].weight;
int index = end_node;
s_path_index.push_back(index) ;
while (true) {
index = path[index].front_index ;
s_path_index.push_back(index);
if (index == 0) {
break;
}
}
}
private:
vector
int node_count; // 结点个数
const int no_edge; // 无通路
const int end_node; // 目的结点
vector
int shortest_path; // 最短路径
};
int main()
{
const int size = 11;
vector
for (int i = 0;i < size; ++ i) {
graph[i].resize (size);
}
for ( i = 0;i < size; ++ i) {
for (int j = 0;j < size; ++ j) {
graph[i][j] = -1;
}
}
graph[0][1] = 2;
graph[0][2] = 3;
graph[0][3] = 4;
graph[1][2] = 3;
graph[1][5] = 2;
graph[1][4] = 7;
graph[2][5] = 9;
graph[2][6] = 2;
graph[3][6] = 2;
graph[4][7] = 3;
graph[4][8] = 3;
graph[5][6] = 1;
graph[5][8] = 3;
graph[6][9] = 1;
graph[6][8] = 5;
graph[7][10] = 3;
graph[8][10] = 2;
graph[9][8] = 2;
graph[9][10] = 2;
ss_shortest_paths ssp (graph, 10);
ssp.shortest_paths ();
ssp.print_spaths ();
getchar();
return 0;
}
二、实验目的:
课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的:
(1)使学生掌握分治法思想
(2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法;
(3)使学生提高对实际问题的分析、设计和实现能力;
(4)为学生后续课程的学习及课程设计打下坚实的实践基础。
三、使用的策略:
分治法算法
四、实验内容:
(一) 问题描述
给定由n个整数(可能为负整数)组成的序列a1,a2,a3,···,an,求该序列的子段和的最大值。当所有整数均为负整数是定义其最大子段和为0,一次定义,所求的最优质值为:max{0、max子段和}。
(二) 算法描述
分治算法的基本思想:
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成
算法设计:
#include "stdafx.h"
int MAXSubsum(int a[],int left,int right){
intsum=0,center,LeftSum,RightSum;
ints1,lefts,s2,rights,i;
if(left==right)
sum=a[left]>0?a[left]:0;
else{
center=(left+right)/2;
//求出第(1)种情况的最大字段和
LeftSum=MAXSubsum(a,left,center);
//求出第(2)种情况的最大字段和
RightSum=MAXSubsum(a,center+1,right);
//求出第(3)种情况的最大字段和
s1=0,lefts=0;
for(i=center;i>=left;i--){
lefts+=a[i];
if(lefts>s1)s1=lefts;
}
//第三种情况左边的和
s2=0,rights=0;
for(i=center+1;i<=right;i++)
{
rights+=a[i];
if(rights>s2)s2=rights;
}
//右边的和
sum=s1+s2;//保存了第三种情况字段和
if(sum if(sum } returnsum; } int main(int argc, char* argv[]) { inta[7]={0,-2,11,-4,13,-5,-2},sum; sum=MAXSubsum(a,1,6); printf("%d\n",sum); getchar(); getchar(); return0; } 用回溯题算法解决背包问题 二、实验目的: 课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的: (1)使学生掌握回溯法的定义 (2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法; (3)使学生提高对实际问题的分析、设计和实现能力; (4)为学生后续课程的学习及课程设计打下坚实的实践基础。 三、使用的策略: 回溯算法 四、实验内容: (一) 问题描述 给定一个最大重量为M的背包和N种物品,已知第i种物品是Wi公斤,其价值为Vi元,编程确定一个装货方案,是的装入背包中的所有物品总价值最大。 (二) 算法描述 回溯算法解决方案: l 回溯算法的基本思想 回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。 设计算法: #include "stdafx.h" #include using namespace std; using namespace std; #define max(a,b)((a)>(b)?(a):(b)) int bestValue=0; void backSearch(int *weight,int *value,int capacity,int num,int *mark,intstep,int tempValue,int tempWeight) { int i; if (step>num) { if (tempValue>bestValue) { bestValue=tempValue; cout< for (i=1;i<=num;i++) { cout< } cout< } return ; } else { if(tempWeight+weight[step]<=capacity) { mark[step]=1; backSearch(weight,value,capacity,num,mark,step+1,tempValue+value[step],tempWeight+weight[step]); } mark[step]=0;//注意 backSearch(weight,value,capacity,num,mark,step+1,tempValue,tempWeight); } } int main() { int capacity,num; int *weight,*value,*mark; int i; printf("请输入包的容量:"); scanf("%d",&capacity); printf("请输入物品的数量:"); scanf("%d",&num); weight=(int*)malloc(sizeof(int)*(num+1)); value=(int*)malloc(sizeof(int)*(num+1)); mark=(int*)malloc(sizeof(int)*(num+1)); for(i=1;i<=num;i++) { printf("请输入第%d件物品的重量:",i); scanf("%d",weight+i); printf("请输入第%d件物品的价值:",i); scanf("%d",value+i); printf("\n"); } backSearch(weight,value,capacity,num,mark,1,0,0); printf("书包可容纳的最大价值为:%d\n",bestValue); free(weight); free(value); free(mark); system("pause"); return 0; } 用贪心算法解决背包问题 二、实验目的: 课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的: (1)使学生掌握贪心算法的定义 (2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法; (3)使学生提高对实际问题的分析、设计和实现能力; (4)为学生后续课程的学习及课程设计打下坚实的实践基础。 三、使用的策略: 贪心算法 四、实验内容: (一) 问题描述 给定一个最大重量为M的背包和N种物品,已知第i种物品是Wi公斤,其价值为Vi元,编程确定一个装货方案,是的装入背包中的所有物品总价值最大。 (二) 算法描述 贪心算法解决方案: l 贪心算法的基本思想 贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。 算法设计: #include "stdafx.h" #include using namespace std; const int N = 3; void Gr(int n,float M,float v[],floatw[],float x[]); int main() { float M = 50;//背包所能容纳的重量 float w[] = {10,20,30}; float v[] = {100,250,300}; float x[N+1]; cout<<"背包所能容纳的重量为:"< cout<<"待装物品的重量和价值分别为:"< for(int i=1; i<=N; i++) { cout<<"["< } Gr(N,M,v,w,x); cout<<"选择装下的物品比例如下:"< for( i=1; i<=N; i++) { cout<<"["< } getchar(); return 0; } void Gr(int n,float M,float v[],floatw[],float x[]) { int i; for (i=1;i<=n;i++) { x[i]=0;//初始化数组x[] } float c=M; for (i=1;i<=n;i++)//物品整件被装下,x[i]=1 { if (w[i]>c) { break; } x[i]=1; c-=w[i]; } //物品i只有部分被装下 if (i<=n) { x[i]=c/w[i]; } }