实验三 贪心算法

实验三 贪心算法
实验三 贪心算法

实验三贪心算法

一、实验目的与要求

1、熟悉多机调度问题的算法;

2、初步掌握贪心算法;

二、实验题

要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。约定,每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。作业不能拆分成更小的子作业。

三、实验提示

1、把作业按加工所用的时间从大到小排序

2、如果作业数目比机器的数目少或相等,则直接把作业分配下去

3、如果作业数目比机器的数目多,则每台机器上先分配一个作业,如下的作业分配时,是选那个表头上s最小的链表加入新作业。

# include

# include

using namespace std;

typedef struct Job //作业

{

int ID;

int time;

}Job;

typedef struct JobNode //作业链表的节点

{

int ID;

int time;

JobNode *next;

}JobNode,*pJobNode;

typedef struct Header //链表的表头

{

int s; //处理机上的时间;

JobNode *next;

}Header,pHeader;

int main()

{

void QuickSort(Job *job,int left,int right); //将job时间排序

void outSort(Job *job,int n); //输出排序

void display(Header *M,int m); //输出每个每台机器处理的工作

序号数

int SelectMin(Header *M,int m); //分配作业时选取机器函数;

void solve(Header *head,Job*job,int n,int m); //作业分配函数;

int m,n;

cout<<"\t\t《多机调度问题》\n";

cout<<"请输入机器台数m:";

cin>>m;

Header *head=new Header [m]; //动态构建数组结构体,用于记录机器的作业时间;

cout<<"请输入作业个数n:";

cin>>n;

Job *job=new Job [n]; //动态构建作业的数组结构体;

cout<<"\n请按序号输入每个作业调度所需时间time:";

for(int i=0;i

{

cin>>job[i].time;

job[i].ID=i;

}

QuickSort(job,0,n-1); //作业排序

outSort(job,n); //输出排序

solve(head,job,n,m); //作业分配

display(head,m); //输出分配

cout<

return 0;

}

int SelectMin(Header* M,int m) //选择s最小的机器序号k;

{

int k=0;

for(int i=1;i

{

if(M[i].s

k=i; //k记录S最小的序号;

}

return k;

}

void QuickSort(Job *job,int left,int right) //小到大,排序

{

int middle=0,i=left,j=right;

Job itemp;

middle=job[(left+right)/2].time;

do

{

while((job[i].time>middle)&&(i

i++;

while((job[j].timeleft))

j--;

if(i<=j)

{

itemp=job[j];

job[j]=job[i];

job[i]=itemp;

i++;

j--;

}

}while(i<=j);

if(left

QuickSort(job,left,j);

if(right>i)

QuickSort(job,i,right);

}

void display(Header *M,int m) //作业分配输出函数;

{

JobNode *p;

for(int i=0;i

{

cout<<"\n第"<

if(M[i].next==0)

continue;

p=M[i].next;

do{

cout<ID<<' ';

p=p->next;

}while(p!=0);

}

}

void outSort(Job *job,int n) //作业时间由大到小排序后输出函数;{

cout<<"\n按工作时间由大到小为:\n时间:\t";

for(int i=0;i

cout<

cout<<"\n序号:\t";

for( i=0;i

cout<

}

void solve(Header *head,Job*job,int n,int m) //作业分配函数;{

int k;

for(int i=0;i

{

JobNode *jobnode=new JobNode;

jobnode->time=job[i].time;

jobnode->ID=job[i].ID;

jobnode->next=0;

head[i].s=jobnode->time;

head[i].next=jobnode;

}

if(i<=m) //n

{

for(i;i

{

head[i].s=0;

head[i].next=0;

}

}

if(n>m)

{

for(i;i

{

JobNode *p;

JobNode *jobnode=new JobNode;

jobnode->time=job[i].time;

jobnode->ID=job[i].ID;

jobnode->next=0;

k=SelectMin(head,m);

p=head[k].next;

head[k].s+=jobnode->time;

while(p->next!=0)

p=p->next;

p->next=jobnode;

}

}

}

运行结果:

一、实验要求与目的

1、熟悉贪心算法的基本原理与适用范围。

2、使用贪心算法编程,求解最小生成树问题。

二、实验内容

1、任选一种贪心算法(Prim或Kruskal),求解最小生成树。对算法进行描述和复杂性分析。编程实现,并给出测试实例

#include

#include

//图中顶点个数

#define V 5

//未在mstSet中的点的集合中,找出最小key的点

int minKey(int key[], bool mstSet[])

{

int min = INT_MAX, min_index;

for (int v = 0; v < V; v++)

if (mstSet[v] == false && key[v] < min)

min = key[v], min_index = v;

return min_index;

}

// 打印MST

int printMST(int parent[], int n, int graph[V][V])

{

printf("Edge Weight\n");

for (int i = 1; i < V; i++)

printf("%d - %d %d \n", parent[i], i, graph[i][parent[i]]);

return 0;

}

// Prim算法

void primMST(int graph[V][V])

{

int parent[V]; // 保持MST信息

int key[V]; // 所有顶点的代价值

bool mstSet[V]; //当前包含在MST中点的集合

// 初始为无穷大

for (int i = 0; i < V; i++)

key[i] = INT_MAX, mstSet[i] = false;

key[0] = 0; //

parent[0] = -1; // 第一个作为树的根。

// MST 有V的顶点

for (int count = 0; count < V-1; count++)

{

int u = minKey(key, mstSet);

// 添加u到MST Set

mstSet[u] = true;

//更新和u相连的顶点的代价

for (int v = 0; v < V; v++)

if (graph[u][v] && mstSet[v] == false && graph[u][v] < key[v]) parent[v] = u, key[v] = graph[u][v];

}

// 打印生成的MST

printMST(parent, V, graph);

}

int main()

{

/* 创建以下的图

2 3

(0)--(1)--(2)

| / \ |

6| 8/ \5 |7

| / \ |

(3)-------(4)

9 */

int graph[V][V] = {{0, 2, 0, 6, 0},

{2, 0, 3, 8, 5},

{0, 3, 0, 0, 7},

{6, 8, 0, 0, 9},

{0, 5, 7, 9, 0},

};

// Print the solution

primMST(graph);

return 0;

}

运行结果:

时间复杂度

这里记顶点数v,边数e

时间复杂度:O(v^2). 如果使用链接表存储的方式并使用堆,复杂度可以为:O(elog2v)

一、实验目的与要求

1、掌握汽车加油问题的算法;

2、进一步掌握贪心算法;

二、实验题

一辆汽车加满油后可以行驶N千米。旅途中有若干个加油站。若要使沿途的加油次数最少,设计一个有效的算法,指出应在那些加油站停靠加油。并证明你的算法能产生一个最优解。

三、实验提示

把两加油站的距离放在数组中,a[1..n]表示从起始位置开始跑,经过n个加油站,a[k]表示

第k-1个加油站到第k个加油站的距离。汽车在运行的过程中如果能跑到下一个站则不加油,否则要加油。(算法略)

#include

#define N 1000

int greedy(int d[],int n,int k)

{

int num = 0;

int i=0;

int s=0;

for( i = 0;i < k;i++)

{

if(d[i] > n)

{

printf("no solution\n");

return 0;

}

}

for( i = 0,s = 0;i < k;i++)

{

s += d[i];

if(s > n)

{

num++;

s = d[i];

}

}

printf("%d\n",num);

return 1;

}

void main()

{

int i,n,k;

int d[N];

printf("请输入汽车可行驶:\n");

scanf("%d",&n);

printf("加油站的个数:\n");

scanf("%d",&k);

for(i=0;i

{

printf("请输入第%d段路的长度: ",i+1);

scanf("%d",&d[i]);

fflush(stdin);

}

greedy(d,n,k+1);

}

运行结果:

四、实验总结

本次实验让我们熟练的掌握了贪心算法的两个重要的性质:最优子结构性质和贪心选择性质。我们只有不断的练习和实验,才能更好的掌握贪心算法,知道贪心算法的优缺点,在什么情况下使用贪心算法才能更好的发挥它的作用。

算法设计与分析实验报告贪心算法

算法设计与分析实验报告 贪心算法 班级:2013156 学号:201315614 姓名:张春阳哈夫曼编码 代码 #include float small1,small2; int flag1,flag2,count; typedefstructHuffmanTree { float weight; intlchild,rchild,parent; }huffman; huffmanhuffmantree[100]; void CreatHuffmanTree(intn,int m) { inti; void select(); printf("请输入%d个节点的权值:",n); for(i=0;i

printf("\n"); for(i=0;i

算法设计与分析实验三

实验三分治算法(2) 一、实验目的与要求 1、熟悉合并排序算法(掌握分治算法) 二、实验题 1、问题陈述: 对所给元素存储于数组中和存储于链表中两中情况,写出自然合并排序算法. 2、解题思路: 将待排序元素分成大小大相同的两个集合,分别对两个集合进行排序,最终将排好序的子集合合并成为所要求的排好序的集合.自然排序是通过一次扫描待排元素中自然排好序的子数组,再进行子数组的合并排序. 三、实验步骤 程序代码: #include const int N=100;//定义不可变常量N //各个函数的声明 void ScanTarget(int target[], int n, int head[], int tail[]); int CountHead(int head[]); void MergeSort(int a[], int head[], int tail[], int m); void MergePass(int x[], int y[], int s, int a[], int b[], int m); void Merge(int c[], int d[], int l, int m, int r); //主函数的定义 void main() { char a; do {

int target[N],head[N],tail[N]; int i=0,n,m; for(; i>n; cout<<"请输入需要排序的数列:" <>target[i]; ScanTarget(target,n,head,tail); m=CountHead(head);//调用求长度的函数 MergeSort(target,head,tail,m);//调用归并排序函数 cout<<"排序后:"<>a; } while(a!='n' && a!='N'); } void ScanTarget(int target[], int n, int head[], int tail[])//定义扫描待排数组的函数;{ int i,j=0,k=0; head[k]=0;

贪心算法经典例题

贪心算法经典例题 发布日期:2009-1-8 浏览次数:1180 本资料需要注册并登录后才能下载! ·用户名密码验证码找回密码·您还未注册?请注册 您的账户余额为元,余额已不足,请充值。 您的账户余额为元。此购买将从您的账户中扣除费用0.0元。 内容介绍>> 贪心算法经典例题 在求最优解问题的过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。 从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。 我们看看下面的例子 例1 均分纸牌(NOIP2002tg) [问题描述] 有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。例如 N=4,4 堆纸牌数分别为: ①9 ②8 ③17 ④ 6 移动3次可达到目的: 从③取 4 张牌放到④(9 8 13 10) -> 从③取 3 张牌放到②(9 11 10 10)-> 从②取 1 张牌放到①(10 10 10 10)。 [输入]:键盘输入文件名。 文件格式:N(N 堆纸牌,1 <= N <= 100) A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000) [输出]:输出至屏幕。格式为:所有堆均达到相等时的最少移动次数。 [输入输出样例] a.in: 4 9 8 17 6 屏慕显示:3 算法分析:设a[i]为第i堆纸牌的张数(0<=i<=n),v为均分后每堆纸牌的张数,s为最小移到次数。 我们用贪心法,按照从左到右的顺序移动纸牌。如第i堆(0

《算法设计与分析》上机实验报告(3)

福州大学数学与计算机科学学院《算法设计与分析》上机实验报告(3)

求任一字符的代码都不是其他字符代码的前缀。这种编码称为前缀码。编码的前缀性质可以使译码方法非常简单;例如001011101可以唯一的分解为0,0,101,1101,因而其译码为aabe。 哈夫曼提出了构造最优前缀码的贪心算法,由此产生的编码方案称为哈夫曼算法。 2.算法的设计思想 哈夫曼编码依据贪心算法来构造最优前缀码,构造思想步骤如下: (1)哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树T。 (2)算法以|C|个叶结点开始,执行|C|-1次的“合并”运算后产生最终所要求的树T。 (3)假设编码字符集中每一字符c的频率是f(c)。以f为键值的优先队列Q用在贪心选择时有效地确定算法当前要合并的2棵具有最小频率的树。一旦2棵具有最小频率的树合并后,产生一棵新的树,其频率为合并的2棵树的频率之和,并将新树插入优先队列Q。经过n-1次的合并后,优先队列中只剩下一棵树,即所要求的树T。 构造过程如图所示: 3.算法正确性证明

由此可知,树T和T'的前缀码的平均码长之差为:

码长,同时,仅最优一位编码不同。 (2)最优子结构性质 二叉树T表示字符集C的一个最优前缀码,x和y是树T 中的两个叶子且为兄弟,z是它们的父亲。若将z当作是具有频率f(z)=f(x)+f(y)的字符,则树T’=T-{x,y}表示字符集C’=C-{x, y} ∪ { z}的一个最优前缀码。因此,有: 如果T’不是C’的最优前缀码,假定T”是C’的最优前缀码,那么有 ,显然T”’是比T更优的前缀码,跟前提矛盾!故T'所表示的C'的前缀码是最优的。 由贪心选择性质和最优子结构性质可以推出哈夫曼算法是正确的,即HuffmanTree产生的一棵最优前缀编码树。 4.哈夫曼编码算法的程序代码 (1)huffman.cpp,程序主文件 1.//huffman 贪心算法哈夫曼算法 2.#include "stdafx.h" 3.#include "BinaryTree.h"

算法设计与分析实验报告

本科实验报告 课程名称:算法设计与分析 实验项目:递归与分治算法 实验地点:计算机系实验楼110 专业班级:物联网1601 学号:2016002105 学生姓名:俞梦真 指导教师:郝晓丽

2018年05月04 日 实验一递归与分治算法 1.1 实验目的与要求 1.进一步熟悉C/C++语言的集成开发环境; 2.通过本实验加深对递归与分治策略的理解和运用。 1.2 实验课时 2学时 1.3 实验原理 分治(Divide-and-Conquer)的思想:一个规模为n的复杂问题的求解,可以划分成若干个规模小于n的子问题,再将子问题的解合并成原问题的解。 需要注意的是,分治法使用递归的思想。划分后的每一个子问题与原问题的性质相同,可用相同的求解方法。最后,当子问题规模足够小时,可以直接求解,然后逆求原问题的解。 1.4 实验题目 1.上机题目:格雷码构造问题 Gray码是一个长度为2n的序列。序列无相同元素,每个元素都是长度为n的串,相邻元素恰好只有一位不同。试设计一个算法对任意n构造相应的Gray码(分治、减治、变治皆可)。 对于给定的正整数n,格雷码为满足如下条件的一个编码序列。 (1)序列由2n个编码组成,每个编码都是长度为n的二进制位串。 (2)序列中无相同的编码。 (3)序列中位置相邻的两个编码恰有一位不同。 2.设计思想:

根据格雷码的性质,找到他的规律,可发现,1位是0 1。两位是00 01 11 10。三位是000 001 011 010 110 111 101 100。n位是前n-1位的2倍个。N-1个位前面加0,N-2为倒转再前面再加1。 3.代码设计:

实验三.哈夫曼编码的贪心算法设计

实验四 哈夫曼编码的贪心算法设计(4学时) [实验目的] 1. 根据算法设计需要,掌握哈夫曼编码的二叉树结构表示方法; 2. 编程实现哈夫曼编译码器; 3. 掌握贪心算法的一般设计方法。 实验目的和要求 (1)了解前缀编码的概念,理解数据压缩的基本方法; (2)掌握最优子结构性质的证明方法; (3)掌握贪心法的设计思想并能熟练运用 (4)证明哈夫曼树满足最优子结构性质; (5)设计贪心算法求解哈夫曼编码方案; (6)设计测试数据,写出程序文档。 实验内容 设需要编码的字符集为{d 1, d 2, …, dn },它们出现的频率为 {w 1, w 2, …, wn },应用哈夫曼树构造最短的不等长编码方案。 核心源代码 #include #include #include typedef struct { unsigned int weight; //用来存放各个结点的权值 unsigned int parent,LChild,RChild; //指向双亲、孩子结点的指针 } HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树 typedef char *HuffmanCode; //动态分配数组,存储哈夫曼编码 ∑=j i k k a

//选择两个parent为0,且weight最小的结点s1和s2 void Select(HuffmanTree *ht,int n,int *s1,int *s2) { int i,min; for(i=1; i<=n; i++) { if((*ht)[i].parent==0) { min=i; break; } } for(i=1; i<=n; i++) { if((*ht)[i].parent==0) { if((*ht)[i].weight<(*ht)[min].weight) min=i; } } *s1=min; for(i=1; i<=n; i++)

C++算法设计(完整版)

本科实验报告 课程名称:算法设计与分析(C++语言) 实验项目:算法设计与分析(C++语言) 实验地点:行勉楼B211 专业班级:软件1426 学号:2014006281 学生姓名:李鹏 指导教师:张晓霞 年月日

实验一分治法合并排序 一、实验目的 1.掌握合并排序的基本思想 2.掌握合并排序的实现方法 3.学会分析算法的时间复杂度 4.学会用分治法解决实际问题 二、实验内容 随机产生一个整型数组,然后用合并排序将该数组做升序排列,要求输出排序前和排序后的数组。 三、实验环境 程序设计语言:c++ 编程工具:microsoft visual studio 2010 四、程序代码 // 实验1_1_随机数组合并排序.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include #include //用于p[i] = rand()%100; #include //用于srand((unsigned long)time(0)); #include using namespace std; constint N = 10; //产生长度为N的数组 //输入数组函数 void input(int *p,int n){ //添加时间种子,可在每次运行产生不同的伪随机数 srand((unsigned long)time(0)); for(inti=0;i

实验3. 贪心算法

实验3.贪心算法 一、实验目的 1.理解贪心算法的基本思想。 2.运用贪心算法解决实际问题。 二、实验环境与地点 1.实验环境:Windows7,Eclipse 2.实验地点:网络工程实验室 三、实验内容与步骤 编写程序完成下列题目,上机调试并运行成功。 1.活动安排问题。 问题:有n个活动的集合A={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。 求解:安排尽量多项活动在该场地进行,即求A的最大相容子集。 设待安排的11个活动的开始时间和结束时间按结束时间的升序排列如下: 将此表数据作为实现该算法的测试数据。 (1)给出算法基本思想; (2)给出用java语言实现程序的代码; 算法: public static int greedySelector(int[] s, int[] f, boolean a[]) { int n = s.length - 1; a[1] = true; int j = 1; int count = 1; for (int i = 2; i <= n; i++) { if (s[i] >= f[j]) { a[i] = true; j = i; count++; } else a[i] = false; } return count; }

2.哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法。统计字符串中各个字符 出现的频率,求各个字符的哈夫曼编码方案。 输入:good good study,day day up 输出:各字符的哈夫曼编码。 算法: 算法中用到的类Huffman定义为: private static class Huffman implements Comparable { Bintree tree; float weight;// 权值 private Huffman(Bintree tt, float ww) { tree = tt; weight = ww; } public int compareTo(Object x) { float xw = ((Huffman) x).weight; if (weight < xw) return -1; if (weight == xw) return 0; return 1; } } 算法huffmanTree描述如下: public static Bintree huffmanTree(float[] f) { // 生成单结点树 int n = f.length; Huffman[] w = new Huffman[n + 1]; Bintree zero = new Bintree(); for (int i = 0; i < n; i++) { Bintree x = new Bintree(); x.makeTree(new MyInteger(i), zero, zero); w[i + 1] = new Huffman(x, f[i]); } // 建优先队列 MinHeap H = new MinHeap(); H.initialize(w, n); // 反复合并最小频率树 for (int i = 1; i < n; i++) { Huffman x = (Huffman) H.removeMin(); Huffman y = (Huffman) H.removeMin(); Bintree z = new Bintree();

2009.1算法设计与分析课程期末试卷-A卷(自测 )

华南农业大学期末考试试卷(A卷)2008学年第一学期考试科目:算法分析与设计 考试类型:(闭卷)考试时间:120 分钟 学号姓名年级专业 一、选择题(20分,每题2分) 1.下述表达不正确的是。 A.n2/2 + 2n的渐进表达式上界函数是O(2n) B.n2/2 + 2n的渐进表达式下界函数是Ω(2n) C.logn3的渐进表达式上界函数是O(logn) D.logn3的渐进表达式下界函数是Ω(n3) 2.当输入规模为n时,算法增长率最大的是。 A.5n B.20log 2n C.2n2 D.3nlog 3 n 3.T(n)表示当输入规模为n时的算法效率,以下算法效率最优的是。A.T(n)= T(n – 1)+1,T(1)=1 B.T(n)= 2n2 C.T(n)= T(n/2)+1,T(1)=1 D.T(n)= 3nlog 2 n 4.在棋盘覆盖问题中,对于2k×2k的特殊棋盘(有一个特殊方块),所需的L型骨 牌的个数是。 A.(4k– 1)/3 B.2k /3 C.4k D.2k 5.在寻找n个元素中第k小元素问题中,若使用快速排序算法思想,运用分治算

法对n个元素进行划分,应如何选择划分基准?下面答案解释最合理。 A.随机选择一个元素作为划分基准 B.取子序列的第一个元素作为划分基准 C.用中位数的中位数方法寻找划分基准 D.以上皆可行。但不同方法,算法复杂度上界可能不同 6.有9个村庄,其坐标位置如下表所示: 现在要盖一所邮局为这9个村庄服务,请问邮局应该盖在才能使到邮局到这9个村庄的总距离和最短。 A.(4.5,0)B.(4.5,4.5)C.(5,5)D.(5,0) 7.n个人拎着水桶在一个水龙头前面排队打水,水桶有大有小,水桶必须打满水, 水流恒定。如下说法不正确? A.让水桶大的人先打水,可以使得每个人排队时间之和最小 B.让水桶小的人先打水,可以使得每个人排队时间之和最小 C.让水桶小的人先打水,在某个确定的时间t内,可以让尽可能多的人打上水D.若要在尽可能短的时间内,n个人都打完水,按照什么顺序其实都一样 8.分治法的设计思想是将一个难以直接解决的大问题分割成规模较小的子问题, 分别解决子问题,最后将子问题的解组合起来形成原问题的解。这要求原问题和子问题。

实验三算符优先分析算法设计与实现

实验三算符优先分析算法的设计与实现 (8学时) 一、实验目的 根据算符优先分析法,对表达式进行语法分析,使其能够判断一个表达式是否正确。通过算符优先分析方法的实现,加深对自下而上语法分析方法的理解。 二、实验要求 1、输入文法。可以是如下算术表达式的文法(你可以根据需要适当改变): E→E+T|E-T|T T→T*F|T/F|F F→(E)|i 2、对给定表达式进行分析,输出表达式正确与否的判断。 程序输入/输出示例: 输入:1+2; 输出:正确 输入:(1+2)/3+4-(5+6/7); 输出:正确 输入:((1-2)/3+4 输出:错误 输入:1+2-3+(*4/5) 输出:错误 三、实验步骤 1、参考数据结构 char *VN=0,*VT=0;//非终结符和终结符数组 char firstvt[N][N],lastvt[N][N],table[N][N]; typedef struct //符号对(P,a) { char Vn; char Vt; } VN_VT; typedef struct //栈 { VN_VT *top; VN_VT *bollow; int size; }stack; 2、根据文法求FIRSTVT集和LASTVT集 给定一个上下文无关文法,根据算法设计一个程序,求文法中每个非终结符的FirstVT 集和LastVT 集。

算符描述如下: /*求 FirstVT 集的算法*/ PROCEDURE insert(P,a); IF not F[P,a] then begin F[P,a] = true; //(P,a)进栈 end; Procedure FirstVT; Begin for 对每个非终结符 P和终结符 a do F[P,a] = false for 对每个形如 P a…或 P→Qa…的产生式 do Insert(P,a) while stack 非空 begin 栈顶项出栈,记为(Q,a) for 对每条形如 P→Q…的产生式 do insert(P,a) end; end. 同理,可构造计算LASTVT的算法。 3、构造算符优先分析表 依据文法和求出的相应FirstVT和 LastVT 集生成算符优先分析表。 算法描述如下: for 每个形如 P->X1X2…X n的产生式 do for i =1 to n-1 do begin if X i和X i+1都是终结符 then X i = X i+1 if i<= n-2, X i和X i+2 是终结符, 但X i+1 为非终结符 then X i = X i+2 if X i为终结符, X i+1为非终结符 then for FirstVT 中的每个元素 a do X i < a ; if X i为非终结符, X i+1为终结符 then for LastVT 中的每个元素 a do a > X i+1 ; end 4、构造总控程序 算法描述如下: stack S; k = 1; //符号栈S的使用深度 S[k] = ‘#’ REPEAT

贪心算法 找零钱问题

学号 《算法设计与分析》 实验报告三 学生姓名 专业、班级 指导教师 成绩 电子与信息工程系

实验三:贪心算法运用练习 一、实验目的 本次实验是针对贪心算法运用的算法设计及应用练习,旨在加深学生对该部分知识点的理解,提高学生运用该部分知识解决问题的能力。 二、实验步骤与要求 1.实验前复习课程所学知识以及阅读和理解指定的课外阅读材料; 2.学生独自完成实验指定内容; 3.实验结束后,用统一的实验报告模板编写实验报告。 4.提交说明: (1)电子版提交说明: a 需要提交Winrar压缩包,文件名为“《算法设计与分析》实验二_学号_姓名”, 如“《算法设计与分析》实验二_09290101_张三”。 b 压缩包内为一个“《算法设计与分析》实验二_学号_姓名”命名的顶层文件夹, 其下为两个文件夹,一个文件夹命名为“源程序”,另一个文件夹命名为“实验 报告电子版”。其下分别放置对应实验成果物。 (2)打印版提交说明: a 不可随意更改模板样式。 b 字体:中文为宋体,大小为10号字,英文为Time New Roman,大小为10号 字。 c 行间距:单倍行距。 (3)提交截止时间:2012年12月7日16:00。 三、实验项目 1.传统的找零钱问题的算法及程序实现。 2.特殊的0-1背包问题的求解:本次求解的0-1背包问题的特点为每种物品各有M件,已知每个物品的单位价值,求使得所获价值最大的装包方案。 四、实验过程 找零钱问题: #include using namespace std; void Zl(double num) { int leave=0; int a[8]; leave = (int)(num*10)%10; a[1] = leave/5;

南京邮电大学算法设计实验报告——动态规划法

实验报告 (2009/2010学年第一学期) 课程名称算法分析与设计A 实验名称动态规划法 实验时间2009 年11 月20 日指导单位计算机学院软件工程系 指导教师张怡婷 学生姓名丁力琪班级学号B07030907 学院(系) 计算机学院专业软件工程

实验报告 实验名称动态规划法指导教师张怡婷实验类型验证实验学时2×2实验时间2009-11-20一、实验目的和任务 目的:加深对动态规划法的算法原理及实现过程的理解,学习用动态规划法解决实际应用中的最长公共子序列问题。 任务:用动态规划法实现求两序列的最长公共子序列,其比较结果可用于基因比较、文章比较等多个领域。 要求:掌握动态规划法的思想,及动态规划法在实际中的应用;分析最长公共子序列的问题特征,选择算法策略并设计具体算法,编程实现两输入序列的比较,并输出它们的最长公共子序列。 二、实验环境(实验设备) 硬件:计算机 软件:Visual C++

三、实验原理及内容(包括操作过程、结果分析等) 1、最长公共子序列(LCS)问题是:给定两个字符序列X={x1,x2,……,x m}和Y={y1,y2,……,y n},要求找出X和Y的一个最长公共子序列。 例如:X={a,b,c,b,d,a,b},Y={b,d,c,a,b,a}。它们的最长公共子序列LSC={b,c,d,a}。 通过“穷举法”列出所有X的所有子序列,检查其是否为Y的子序列并记录最长公共子序列并记录最长公共子序列的长度这种方法,求解时间为指数级别的,因此不可取。 2、分析LCS问题特征可知,如果Z={z1,z2,……,z k}为它们的最长公共子序列,则它们一定具有以下性质: (1)若x m=y n,则z k=x m=y n,且Z k-1是X m-1和Y n-1的最长公共子序列; (2)若x m≠y n且x m≠z k,则Z是X m-1和Y的最长公共子序列; (3)若x m≠y n且z k≠y n,则Z是X和Y的最长公共子序列。 这样就将求X和Y的最长公共子序列问题,分解为求解较小规模的问题: 若x m=y m,则进一步分解为求解两个(前缀)子字符序列X m-1和Y n-1的最长公共子序列问题; 如果x m≠y n,则原问题转化为求解两个子问题,即找出X m-1和Y的最长公共子序列与找出X 和Y n-1的最长公共子序列,取两者中较长者作为X和Y的最长公共子序列。 由此可见,两个序列的最长公共子序列包含了这两个序列的前缀的最长公共子序列,具有最优子结构性质。 3、令c[i][j]保存字符序列X i={x1,x2,……,x i}和Y j={y1,y2,……,y j}的最长公共子序列的长度,由上述分析可得如下递推式: 0 i=0或j=0 c[i][j]= c[i-1][j-1]+1 i,j>0且x i=y j max{c[i][j-1],c[i-1][j]} i,j>0且x i≠y j 由此可见,最长公共子序列的求解具有重叠子问题性质,如果采用递归算法实现,会得到一个指数时间算法,因此需要采用动态规划法自底向上求解,并保存子问题的解,这样可以避免重复计算子问题,在多项式时间内完成计算。 4、为了能由最优解值进一步得到最优解(即最长公共子序列),还需要一个二维数组s[][],数组中的元素s[i][j]记录c[i][j]的值是由三个子问题c[i-1][j-1]+1,c[i][j-1]和c[i-1][j]中的哪一个计算得到,从而可以得到最优解的当前解分量(即最长公共子序列中的当前字符),最终构造出最长公共子序列自身。

贪心算法解汽车加油问题实验报告

计算机算法与分析 设计报告 班级:信管一班信管二班 姓名(学号):赵立贺(060340219) 赵艳(060340114)刘辉(060340125)王勇(060340116)万玉琪(060340213)刘旺(060340205)指导教师:赵晓峰姚天祥 设计地点:信息系统实验室 信息管理系 2008年12月13日

一、实验名称: 用贪心算法、回溯算法、动态规划等解决汽车加油次数最少问题。 二、实验目的: 课程设计是《计算机算法与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的: (1)使学生掌握线性表、栈、队列、串、树、二叉树、图、集合等各种典型抽象数据类型的数学模型及其所支持基本运算的实现方法; (2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法; (3)使学生提高对实际问题的分析、设计和实现能力; (4)为学生后续课程的学习及课程设计打下坚实的实践基础。 三、使用的策略: 贪心算法、回溯算法等。 四、实验内容: (一)问题描述 一辆汽车加满油后可以行驶N千米。旅途中有若干个加油站。指出若要使沿途的加油次数最少,设计一个有效的算法,指出应在那些加油站停靠加油。 给出N,并以数组的形式给出加油站的个数及相邻距离,指出若要使沿途的加油次数最少,设计一个有效的算法,指出应在那些加油站停靠加油。要求:算法执行的速度越快越好。 (二)问题分析(前提行驶前车里加满油) 对于这个问题我们有以下几种情况:设加油次数为k,每个加油站间距离为a[i];i=0,1,2,3……n 1.始点到终点的距离小于N,则加油次数k=0; 2.始点到终点的距离大于N, A 加油站间的距离相等,即a[i]=a[j]=L=N,则加油次数最少k=n; B 加油站间的距离相等,即a[i]=a[j]=L>N,则不可能到达终点; C 加油站间的距离相等,即a[i]=a[j]=L

贪心算法求解最优服务次序问题

实验名称:贪心算法实例编程 求解最优服务次序问题 1、实验目的: 1)理解贪心算法的概念 2)掌握贪心算法的基本要素 3)掌握设计贪心算法的一般步骤 4)针对具体问题,能应用贪心算法设计有效算法 5)用C++实现算法,并且分析算法的效率 2、实验设备及材料: 硬件设备:PC机 机器配置:双核cpu频率2.2GHz,内存2G 操作系统:Windows 7 开发工具:VC++6.0 3、实验内容: ①问题描述 设有n个顾客同时等待一项服务。顾客i需要的服务时间为t i,1≤i≤n。 应如何安排n个顾客的服务次序才能使平均等待时间达到最小?平均等待时间是n恶搞顾客等待服务时间的总和除以n。 ②编程任务 对于给定的n个顾客需要的服务时间,计算最优服务次序。 ③样例 例如,现在有5个顾客,他们需要的服务时间分别为:56,12,5,99,33。 那么,按照所需服务时间从小到大排序为:5,12,33,56,99。排序后的顾客等待服务完成的时间为:5,17,50,106,205;和为:383;平均等待时间为:76.6。

4、实验方法步骤及注意事项: ①实验步骤 a、分析问题,确定最优的贪心选择; b、针对贪心选择过程进行算法设计; c、举例验证算法的正确性; d、上机调试算法。 ②解题思路 1)求解最优服务次序问题的贪心策略为:先为所需服务时间最短的顾客服务。 2)使用贪心算法求解最优服务次序问题的算法,用C++语言描述。 ①.最优值:(贪心算法) text(int n,int x[],int s[])//s[]为保存每个顾客等待时间的数组 { int i; int sum=0; for(i=0;i0){ s[i]=x[i]+s[i-1]; sum+=s[i];} else { s[i]=x[i]; sum+=s[i]; } } return sum/n; } ②.最优解:(快速排序) void QuickSort(int e[], int first, int end) { int i=first,j=end,key=e[first]; while(i=key) j--; e[i]=e[j]; while(ii+1) QuickSort(e,i+1,end); }

算法与设计实验报告

算法与分析实验报告软件工程专业 安徽工业大学 指导老师:许精明

实验内容 1:杨辉三角 2:背包问题 3:汉诺塔问题 一:实验目的 1:掌握动态规划算法的基本思想,学会用其解决实际问题。 2:通过几个基本的实验,提高算法分析与设计能力,提高动手操作能力和培养良好的编程习惯。 二:实验内容 1:杨辉三角 2:背包问题 3:汉诺塔问题 实验一:杨辉三角

问题分析: ①每行数字左右对称,由1开始逐渐变大,然后变小,回到1。 ②第n行数之和为2^n。 ③下一行每个数字等于上一行的左右两个数字之和。 算法设计及相关源代码: public void yanghui(int n) { int[] a = new int[n]; if(n==1){ System.out.println(1); }else if(n==2) { System.out.print(1 + " " +1); }else{ a[1]=1; System.out.println(a[1]); a[2]=1;

System.out.println(a[1]+" "+a[2]); for(int i=3;i<=n;i++){ a[1]=a[i]=1; for(int j=i-1;j>1;j--){ a[j]=a[j]+a[j-1]; } for(int j=1;j<=i;j++){ System.out.print(a[j]+" "); } System.out.println(); } } } 实验结果:n=10 实验二:0-1背包问题 问题分析::令V(i,j)表示在前i(1<=i<=n)个物品中能够装入容量为就 j(1<=j<=C)的背包中的物品的最大价值,则可以得到如下的动态规划函数: (1) V(i,0)=V(0,j)=0 (2) V(i,j)=V(i-1,j) j

实验二(贪心算法)

华东师范大学计算机科学技术系上机实践报告 课程名称:算法设计与分析年级:05上机实践成绩: 指导教师:柳银萍姓名:张翡翡 上机实践名称:贪心算法学号:10052130119上机实践日期:2007-4-10 上机实践编号:NO.2组号:上机实践时间:10:00-11:30 一、目的 了解熟悉掌握贪心算法实质并学会灵活运用,从而解决生活中一些实际问题。 二、内容与设计思想 1.超市的自动柜员机(POS)要找给顾客各种数值的现金,表面上看,这是一个很简单的任务,但交给机器办就不简单了。你作为一个计算机专家,要求写一个程序来对付这个“简单”的问题。 你的自动柜员机有以下的币种:100元,50元,20元,10元,5元,2元,1元。你可以假设每种钱币的数量是无限的。现在有一笔交易,需要找个客户m元,请你设计一个算法,使得找给顾客的钱币张数最少。 要求: 输入:第一行仅有一个整数n(0

算法设计与分析实验报告 统计数字问题

算法设计与分析实验报告 实验名称统计数字问题评分 实验日期年月日指导教师 姓名专业班级学号 一.实验要求 1、掌握算法的计算复杂性概念。 2、掌握算法渐近复杂性的数学表述。 3、掌握用C++语言描述算法的方法。 4.实现具体的编程与上机实验,验证算法的时间复杂性函数。 二.实验内容 统计数字问题 1、问题描述 一本书的页码从自然数1 开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如,第6 页用数字6 表示,而不是06 或006 等。数字计数问题要求对给定书的总页码n,计算出书的全部页码中分别用到多少次数字0,1,2, (9) 2、编程任务 给定表示书的总页码的10 进制整数n (1≤n≤109) 。编程计算书的全部页码中分别用到多少次数字0,1,2, (9) 三.程序算法 将页码数除以10,得到一个整数商和余数,商就代表页码数减余数外有多少个1—9作为个位数,余数代表有1—余数本身这么多个数作为剩余的个位数,此外,商还代表1—商本身这些数出现了10次,余数还代表剩余的没有计算的商的大小的数的个数。把这些结果统计起来即可。 四.程序代码 #include int s[10]; //记录0~9出现的次数 int a[10]; //a[i]记录n位数的规律 void sum(int n,int l,int m) { if(m==1) {

int zero=1; for(int i=0;i<=l;i++) //去除前缀0 { s[0]-=zero; zero*=10; } } if(n<10) { for(int i=0;i<=n;i++) { s[i]+=1; } return; }//位数为1位时,出现次数加1 //位数大于1时的出现次数 for(int t=1;t<=l;t++)//计算规律f(n)=n*10^(n-1) { m=1;int i; for(i=1;i

哈夫曼编码_贪心算法

淮海工学院计算机工程学院实验报告书 课程名:《算法分析与设计》 题目:实验3 贪心算法 哈夫曼编码 班级:软件102班 学号:11003215 姓名:鹿迅

实验3 贪心算法 实验目的和要求 (1)了解前缀编码的概念,理解数据压缩的基本方法; (2)掌握最优子结构性质的证明方法; (3)掌握贪心法的设计思想并能熟练运用 (4)证明哈夫曼树满足最优子结构性质; (5)设计贪心算法求解哈夫曼编码方案; (6)设计测试数据,写出程序文档。 实验内容 设需要编码的字符集为{d 1, d 2, …, dn },它们出现的频率为 {w 1, w 2, …, wn },应用哈夫曼树构造最短的不等长编码方案。 实验环境 Turbo C 或VC++ 实验学时 2学时,必做实验 数据结构与算法 struct huffman { double weight; //用来存放各个结点的权值 int lchild,rchild,parent; //指向双亲、孩子结点的指针 }; 核心源代码 #include #include using namespace std; struct huffman { double weight; int lchild,rchild,parent; }; static int i1=0,i2=0; int Select(huffman huff[],int i) { ∑=j i k k a

int min=11000; int min1; for(int k=0;k

相关文档
最新文档