实验二 贪心算法-最少活动会场安排问题

合集下载

贪心法解活动安排问题(计算机算法设计与分析)

贪心法解活动安排问题(计算机算法设计与分析)

实验报告
课程名称:算法设计与分析实验名称:贪心法解活动安排问题任课教师:专业:计算机科学与技术
班级: 20xx 级x班学号:
姓名:完成日期: 20xx年x月xx日
五、实验总结
在做本实验之前,自己看了课本上所列举的贪心法解活动安排问题的代码,代码很简单,很容易理解,于是就按课本的代码实现。

通过几个测试用例测试发现结果不对,后来发现自己忘了进行贪心法的一个前提条件,事先没有按各个活动结束时间对所有活动进行非递减排序,所以才会导致结果错误。

经过修正后,自己真正理解了贪心法解活动安排问题的原理,重新完成本次实验内容也是很顺利,在编程方面没有遇到什么困难。

贪心法解活动安排问题(计算机算法设计与分析)

贪心法解活动安排问题(计算机算法设计与分析)

实验报告
课程名称:算法设计与分析实验名称:贪心法解活动安排问题任课教师:专业:计算机科学与技术
班级: 20xx 级x班学号:
姓名:完成日期: 20xx年x月xx日
五、实验总结
在做本实验之前,自己看了课本上所列举的贪心法解活动安排问题的代码,代码很简单,很容易理解,于是就按课本的代码实现。

通过几个测试用例测试发现结果不对,后来发现自己忘了进行贪心法的一个前提条件,事先没有按各个活动结束时间对所有活动进行非递减排序,所以才会导致结果错误。

经过修正后,自己真正理解了贪心法解活动安排问题的原理,重新完成本次实验内容也是很顺利,在编程方面没有遇到什么困难。

算法设计与分析课件--贪心法-会场安排问题

算法设计与分析课件--贪心法-会场安排问题
7
4.1 概述
◼ 贪心法基本思想的推论
❖精髓是“今朝有酒今朝醉”; ❖每个阶段的决策一旦做出就不可更改。不允许回溯。 ❖ 贪心法根贪心法的实际意义和学术价值:
❖可算得上是最接近人们日常思维的一种解题策略; ❖简单、直接和高效; ❖对范围相当广泛的许多实际问题通常都能够产生整
A {1}; //首先选择会议1
k 1;
//已被选择会议集合中最晚结束的会议(k)
for m 2 to n do
if B[m] >= E[k] then //会议m开始时间不小于会议k结束时间
A A ∪ {m}; //将会议m加入到集合A中
k m;
//此时集合A中最晚结束的会议为m
return A;
✓ 因此,会场安排问题的最优子结构性质得到证明
19
12
4.2 会场安排问题
◼ 几种贪心选择策略:
❖选择最早开始时间且不与已安排会议重叠的会议: ✓但如果会议的使用时间无限长,如此选择策略就只 能安排1个会议来使用资源。不可行。
❖选择使用时间最短且不与已安排会议重叠的会议: ✓但如果会议的开始时间最晚,如此选择策略也就只 能安排1个会议来使用资源。不可行。
❖选择最早结束时间且不与已安排会议重叠的会议: ✓如果选择开始时间最早且使用时间最短的会议,较 为理想。而此即结束时间最早的会议。可行。
13
4.2 会场安排问题
◼ 求解步骤:
❖步骤1:初始化,并按会议结束时间非减序排序。
✓开始时间存入数组B,结束时间存入数组E中; ✓按照结束时间的非减序排序E,B需做相应调整; ✓集合A存储解。如果会议i在集合A中,当且仅当其被选中。
6
4.1 概述
◼ 贪心法基本思想的推论

贪心算法经典问题:活动安排,背包问题,最优装载,单源最短路径 Dijiksra,找零钱问题,多机调度

贪心算法经典问题:活动安排,背包问题,最优装载,单源最短路径 Dijiksra,找零钱问题,多机调度

活动安排public static int greedySelector(int [] s, int [] f, boolean a[]){ //s[]开始时间f[]结束时间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;}背包问题void Knapsack(int n,float M,float v[],float w[],float x[]){ Sort(n,v,w); //以每种物品单位重量的价值Vi/Wi从大到小排序int i;for (i=1;i<=n;i++) x[i]=0;float c=M;for (i=1;i<=n;i++){ if (w[i]>c) break;x[i]=1;c-=w[i];}if (i<=n) x[i]=c/w[i]; //允许放入一个物品的一部分}最优装载void Loading(int x[], T ype w[], T ype c, int n){ int *t = new int [n+1]; //t[i]要存的是w[j]中重量从小到大的数组下标Sort(w, t, n); //按货箱重量排序for (int i = 1; i <= n; i++) x[i] = 0; //O(n)for (int i = 1; i <= n && w[t[i]] <= c; i++){x[t[i]] = 1; c -= w[t[i]];} //调整剩余空间}单源最短路径Dijiksratemplate<class Type>void Dijikstra(int n, int v, Type dist[], int prev[], Type **c){ //c[i][j]表示边(i,j)的权,dist[i]表示当前从源到顶点i的最短特殊路径bool s[maxint];for(int i= 1;i<=n; i++){ dist[i]=c[v][i]; s[i]=false;if(dist[i]==maxint) prev[i]=0;else prev[i]=v;}dist[v]=0 ; s[v]=true;for(int i=1;i<n;i++){ int temp = maxint, u = v;for(int j= 1;j<=n; j++)if( (!s[j])&&(dist[j]<temp) ){u= j ; temp=dist[j]; }s[u]= true;for(int j= 1;j<=n;j++)if( (!s[j])&&(c[u][j])<maxint){ Type newdist = dist[u]+c[u][j];if(newdist<dist[j]) {dist[j]= newdist; prev[j]=u; } }}//ENDFOR}//END找零钱问题#define NUM 4void main(){ int m[NUM]={25,10,5,1};int n; //假设n=99cin>>n;cout<<n<<"的找钱方案为:";for(int i=0;i<NUM;i++)while(n>=m[i]&&n>0){cout<<m[i]<<" ";n-=m[i];}}//END多机调度#define N 10#define M 3void sort(int t[],int n);int set_work1(int t[],int n);int max(int t[],int num);int min(int t[],int m);int set_work2(int t[],int n);static int time[N]={2,8,18,32,50,72,98,128,182,200},s[M]={0,0,0};void main(){sort(time,N);if(M>=N) //作业数小于机器数cout<<set_work1(time,N)<<endl;elsecout<<set_work2(time,N)<<endl;}void sort(int t[],int n){for(int k=0;k<n-1;k++) //用选择法将处理时间从大到小排序{int j=k;for (int i=k; i<n; i++)if (t[i]>t[j]) j=i;{int temp=t[j];t[j]=t[k];t[k]=temp;}}}int max(int t[],int num) //max函数求解处理时间总和最长{int max=t[0];for(int i=1;i<num;i++)if(max<t[i]) max=t[i];return max;}int min(int t[],int m){int min=0; //min记录目前处理作业时间和最小的机器号for(int i=1;i<m;i++)if(s[min]>s[i]) min=i;return min;}int set_work1(int t[],int n){ int m=0;for(int i=0;i<n;i++) //分派作业s[m++]+=t[i];return max(s,N);}int set_work2(int t[],int n){ for(int i=0;i<n;i++)s[min(s,M)]+=t[i];return max(s,M);}。

贪心算法(会场安排问题、区间选点)

贪心算法(会场安排问题、区间选点)

贪⼼算法(会场安排问题、区间选点)学习算法课程之后的第⼀次记录,渐渐的,程序设计考虑的因素增多,程序=数据结构+算法,这个等式让我深有体会。

从开始简单的C++编程,再到选择合适数据结构,现在需要更进⼀步,从算法层次上考虑程序执⾏的效率。

我对算法的理解是⽤更少的开销获得更优的执⾏效果。

分治法、动态规划在此之前没有记录下来,学到贪⼼算法的时候,觉得需要总结⼀下学过的东西,也能更好的理解。

动态规划的设计,要满⾜最优⼦结构性质和重叠⼦问题,采⽤⾃底向上的策略,计算出最优值,找到整体最优解。

这个过程有时候挺难的,主要在写出递归式,要⾃底向上填表。

贪⼼策略有点像动态规划,但在⼀些⽅⾯是不同的,有时候贪⼼算法的思想更容易想到。

它要满⾜⼦问题最优⽽得到整体最优?两个条件:最优⼦结构性质和贪⼼选择性质。

满⾜贪⼼选择性质⼀定满⾜最优⼦结构性质,⽽满⾜最优⼦结构性质不⼀定满⾜贪⼼选择性质,⽐如背包问题可以⽤贪⼼算法解决,⽽0-1背包问题只能⽤动态规划。

典型的贪⼼问题活动安排,有n个活动,给出开始时间和结束时间,要尽可能安排多的活动(时间互相不冲突)。

解决这个问题正确的贪⼼思想是以每个活动结束时间为⽐较变量,按结束时间升序排好活动次序,接着就进⾏⽐较选择。

⽽会场安排问题与活动⼜有些不同之处,下⾯是我的解题过程。

7-2 会场安排问题 (20 分)假设要在⾜够多的会场⾥安排⼀批活动,并希望使⽤尽可能少的会场。

设计⼀个有效的贪⼼算法进⾏安排。

(这个问题实际上是著名的图着⾊问题。

若将每⼀个活动作为图的⼀个顶点,不相容活动间⽤边相连。

使相邻顶点着有不同颜⾊的最⼩着⾊数,相应于要找的最⼩会场数。

)输⼊格式:第⼀⾏有 1 个正整数k,表⽰有 k个待安排的活动。

接下来的 k⾏中,每⾏有 2个正整数,分别表⽰ k个待安排的活动开始时间和结束时间。

时间以 0 点开始的分钟计。

输出格式:输出最少会场数。

输⼊样例:51 2312 2825 3527 8036 50输出样例:3#include<iostream>#include<algorithm>using namespace std;struct node {int begin;int end;int flag;//标记该活动是否被安排,0表⽰未安排,1表⽰已安排}t[10001];int cmp(const node &a,const node &b)//⽐较规则:以结束时间升序排列{return a.end<b.end;}int main(){int i,j,n;node temp;cin>>n;for(i=0;i<n;i++){cin>>t[i].begin>>t[i].end;t[i].flag=0;}sort(t,t+n,cmp);int sum=0;//总共需要的会场数量for(i=0;i<n;i++)//⽅法2{if(!t[i].flag)//找到未安排的活动,进⾏场地安排{sum++;int p=i;for(j=p+1;j<n;j++)//当前活动结束时间与下⼀个活动开始不相交,则安排到同⼀个会场{if(t[p].end<=t[j].begin&&!t[j].flag){p=j;t[j].flag=1;}}t[i].flag=1;}}cout<<sum;return0;}View Code贪⼼策略为:把尽可能多的时间互不冲突的活动安排到⼀个会场,若活动时间交叉,则在安排到另⼀个会场。

会场安排问题(贪心)

会场安排问题(贪心)

会场安排问题(贪⼼)
思路:
能放在⼀个会场⾥的活动的前提是,当前活动的开始时间⼤于等于上⼀个活动的结束时间。

⾸先把⼀个活动的开始时间和结束时间放在两个数组中再进⾏排序,这样得到的就是最⼩开始时间和最⼩结束时间,k初值为0,只要当前的开始时间⼩于结束时间,k++,由于结束时间是降序的,如果不⼩于这个结束时间,就后移⼀位,这样就得到了会场的次数。

贪⼼算法的思想就是只考虑当前的情况。

⽽不顾虑全局最优,所以我们只要能保证下⼀个活动的开始时间能⼩于这个活动的结束时间就⾏。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
int a[10005],b[10005];
for(int i = 0; i < n; i++) {
cin >> a[i] >> b[i];
}
sort(a,a+n);
sort(b,b+n);
int k = 0,j = 0;
for(int i = 0; i < n; i++) {
if(a[i] < b[j]) k++;
else j++;
}
cout << k << endl;
return0;
}。

贪心算法活动安排问题

贪心算法活动安排问题

活动安排问题,对每项活动的按照结束时间非减序排列。

然后选第一个。

按照第一个的结束时间来看接下去怎么选,以此类推。

•第一步二-选择活动1作为第一个被选中的活动,并将活动1的结束时间作为判断下一个活动是否被选中的依据;•第二步’-判断活动2与活龙T是否相容-即引2]是否大于或等于耳];1结果土不相容,活动2没有被选中,活动1的结束时间仍作为判断下一个活动是否被选中的依据•第三步M-判断活动3与活或T是否相容•即引3]是否大于或等于耳1]:结果士不相容,活动礙有被选中,活动1的结束时间仍作为判断下一个活动是否被选中的依据•第四步&-判斷活动4与活动T是否相容-即H4]是否大于或等于di]:结果:相容,活动4袱选中,活动4的结束时间将作为判断下一个活动是否被选中的依据10贪心选择性质的证明:1.活动安排问题的一个最优解是以贪心选择开始。

即最优解包含第一个活动(叫做活动1 )。

证明:假设有一个最优解叫做A。

它的活动也是以结束时间的非减序进行排列。

假设A中第一个活动叫做K。

如果K是我们的活动1,则A就是以活动1开始的。

如果K不是活动1•则把K从A中去掉,并加上活动1,而且活动1是相容的是因为活动1的结束时间最早。

所以证明了活动安排问题的一个最优解是以贪心选择开始。

最优子结构的证明:把起始时间大于活动1的结束时间的活动去掉,A也可以把K去掉,这样子有一个递推的关系就是(总活动中)接下去那个与活动1相容的解必然可以相容在最优解(A-K)里面。

(因它又可以化为一个贪心选择的开始)所以每一步做出的贪心选择将使得原问题化为规模变小的相似的子问题。

贪心算法解决活动安排问题

贪心算法解决活动安排问题
待安排的11个活动的开始时间和结束时间按结束时间的 非减序排列如下:
表1 安排活动非减序时间表
-
5
贪心算法实现
贪心算法的计算过 程如下图所示。图 中每行相应于算法 的一次迭代。阴影 长条表示的活动是 已选入集合A的活动 ,而空白长条表示 的活动是当前正在 检查相容性的活动 。
图-1 贪心算法的计算过程图
减序算法
贪心算法
时间复杂度 O(n2)
O(nlogn) O(n)
-
8
小组任务分工
1. 算法: 2. 李文治 3. 2. PPT: 4. 制作:陈平,谢华欣,韩月梅 5. 3.文档: 6. 制作:陈平,谢华欣,韩月梅
-
-
返回
-
贪心算法算法思想及分析 Nhomakorabea活动安排运用贪心算法的思路为,尽可能多的使更多的 事件得到资源的安排。按这种方法选择相容活动为未安 排活动留下尽可能多的时间。也就是说,该算法的贪心 选择的意义是使剩余的可安排时间段极大化,以便安排 尽可能多的相容活动。实现方法是在满足相容的条件下, 使结束时间靠前的活动得到资源,这样就为后续时间留 下更多的安排时间,以使更多的活动得到安排。
运用贪心算法解决活动安排问题
Using the greedy algorithm to solve the problem of activity arrangement
组长:李文治 组员: 陈平 谢华欣 韩月梅
内容提要
1 问题描述 2 算法思想及分析 3 实验及结果 4 实验总结
-
问题描述
问题描述
陈平谢华欣韩月梅运用贪心算法解决活动安排问题usingthegreedyalgorithmtosolvetheproblemofactivityarrangement问题描述实验及结果实验总结算法思想及分析问题描述设有n个活动的集合e12n其中每个活动都要求使用同一资源如演讲会场等而在同一时间内只有一个活动能使用这一资源
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

中原工学院计算机学院
实验报告
实验项目名称实验二、最少活动会场安排问题课程名称算法设计与分析
学生姓名梁斐燕
学生学号************
所在班级网络14卓越
学科专业网络工程
任课教师吴志刚
完成日期2016年月日
实验二最少活动会场安排问题
一、实验目的
1.掌握贪心算法的基本概念和两个基本要素
2.熟练掌握贪心算法解决问题的基本步骤。

3.学会利用贪心算法解决实际问题。

二、实验内容
•问题描述:
•题目一:假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。

设计一个有效的贪心算法来进行安排,试编程实现。

•题目二:一辆汽车加满油后,可行使n千米。

旅途中有若干个加油站。

若要使沿途加油次数最少,设计一个有效算法,指出应在哪些加油站停靠加油。

•数据输入:个人设定,由键盘输入。

•要求:
–上述题目任选一做。

上机前,完成程序代码的编写
–独立完成实验及实验报告
三、实验步骤
㈠、数据结构与核心算法的设计描述
提示:题目一:参考教材活动安排问题;有关队列操作参考数据结构。

void GreedySelector(int n, int *s, int *f, int *A) {
//用集合A来存储所选择的活动
A[1] = TURE; //默认从第一次活动开始执行
int j = 1; //j记录最近一次加入到A中的活动
for (int i = 2; i <= n; i++) { //f[j]为当前集合A中所有活动的最大结束时间//活动i的开始时间不早于最近加入到集合A中的j的时间f[j]
if (s[i] >= f[j]) {
A[i] = TURE; //当A[i]=TURE时,活动i在集合A中
j = i;
}
else A[i] = FALSE;
}
}
㈡、函数调用及主函数设计
㈢程序调试及运行结果分析
㈣实验总结
在做本实验之前,自己看了课本上所列举的贪心法解活动安排问题的代码,代码很简单,很容易理解,于是就按课本的代码实现。

通过几个测试用例测试发现结果不对,后来发现自己忘了进行贪心法的一个前提条件,事先没有按各个活动结束时间对所有活动进行非递减排序,所以才会导致结果错误。

经过修正后,自己真正理解了贪心法解活动安排问题的原理。

四、主要算法流程图及程序清单
1、主要算法流程图:
快速排序产生中间数贪心算法实现活动安排主函数调用
2、程序清单
(程序过长,可附主要部分)
#include"stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#define N 50
#define TURE 1
#define FALSE 0
int s[N];/*开始时间*/
int f[N];/*结束时间*/
int A[N];/*用A存储所有的*/
void GreedySelector(int n, int *s, int *f, int *A);
int Partition(int *b, int *a, int p, int r)
{
int k, m, y, i = p, j = r + 1;
int x = a[p]; y = b[p];
while (1) {
while (a[++i]<x);
while (a[--j]>x);
if (i >= j)
break;
else {
k = a[i]; a[i] = a[j]; a[j] = k; m = b[i]; b[i] = b[j]; b[j] = m;
}
}
a[p] = a[j];
b[p] = b[j];
a[j] = x;
b[j] = y;
return j;
}
void QuickSort(int *b, int *a, int p, int r)
{
int q; if (p<r)
{
q = Partition(b, a, p, r);
QuickSort(b, a, p, q - 1);/*对左半段排序*/
QuickSort(b, a, q + 1, r);/*对右半段排序*/
}
} //产生中间数
int main()
{
int n = 0, i;
while (n <= 0 || n>50)
{
printf("\n");
printf("请输入活动的个数:");
scanf_s("%d", &n);
if (n <= 0) printf("请输入大于零的数!");
else if (n>50) printf("请输入小于50的数!");
}
printf("\n请分别输入开始时间s[i]和结束时间f[i]:\n\n");
for (i = 1; i <= n; i++)
{
printf("s[%d]=", i, i);
scanf_s("%d", &s[i]);
printf("f[%d]=", i, i);
scanf_s("%d", &f[i]);
printf("\n");
}
QuickSort(s, f, 1, n); //按结束时间非减序排列
printf("按结束时间非减序排列如下:\n"); /*输出排序结果*/
printf("\n 序号\t开始时间结束时间\n");
printf("-------------------------\n"); for (i = 1; i <= n; i++)
printf(" %d\t %d\t %d\n", i, s[i], f[i]);
printf("-------------------------\n");
GreedySelector(n, s, f, A);//贪心算法实现活动安排
printf("安排的活动序号依次为:");
for (i = 1; i <= n; i++)
{
if (A[i])
printf("\n%d ", i);
} printf("\n");
system("pause");
return 0;
} //快速排序
//产生中间数
//贪心算法实现活动安排
void GreedySelector(int n, int *s, int *f, int *A) {
//用集合A来存储所选择的活动
A[1] = TURE; //默认从第一次活动开始执行
int j = 1; //j记录最近一次加入到A中的活动
for (int i = 2; i <= n; i++) { //f[j]为当前集合A中所有活动的最大结束时间//活动i的开始时间不早于最近加入到集合A中的j的时间f[j]
if (s[i] >= f[j]) {
A[i] = TURE; //当A[i]=TURE时,活动i在集合A中
j = i;
}
else A[i] = FALSE;
}
}。

相关文档
最新文档