[关闭]
@rg070836rg 2019-05-11T21:43:15.000000Z 字数 1741 阅读 1411

算法概论实验八 贪心法

算法概论实验


  1. 实验八
  2. 实验目的与要求:
  3. 1 掌握贪心法的基本思想和设计方法。
  4. 1.区间调度问题
  5. 【问题描述】
  6. 给定n个活动,其中的每个活动ai包含一个起始时间si与结束时间fi。设计与实现算法从n个活动中找出一个最大的相互兼容的活动子集S
  7. 要求:分别设计动态规划与贪心算法求解该问题。其中,对贪心算法分别给出递归与迭代两个版本的实现。

贪心法迭代

  1. #include "stdafx.h"
  2. #include <iostream>
  3. using namespace std;
  4. int GetSet(int *si, int *fi, int n)
  5. {
  6. //创建一个记录数组,用于最后判定是否选取
  7. bool *result=new bool[n];
  8. memset(result, false, sizeof(result));
  9. result[0] = true;//初始设定
  10. int selected_index = 0;//第一个选中的
  11. for (int i = 1; i < n;i++)
  12. {
  13. if (fi[selected_index] <= si[i])//这种情况下是能够兼容的
  14. {
  15. result[i] = true;
  16. selected_index = i;
  17. }
  18. }
  19. //输出
  20. int nct = 0;
  21. cout << "最大兼容子集为:";
  22. for (int i = 0; i < n;i++)
  23. {
  24. if (result[i]==true)
  25. {
  26. cout << i + 1 << "\t";
  27. nct++;
  28. }
  29. }
  30. return nct;
  31. }
  32. int main()
  33. {
  34. int si[] = {1,3,0,5,3,5,6,8,8,2,12};
  35. int fi[] = {4,5,6,7,8,9,10,11,12,13,14};
  36. int n = 11;
  37. cout << endl<<"省去排序过程,最兼容活动子集的数目为:"<< GetSet(si, fi, n);
  38. return 0;
  39. }

贪心法 递归

每次递归,将问题的规模减少1~n,

  1. #include "stdafx.h"
  2. #include <iostream>
  3. using namespace std;
  4. //i是上一个符合条件的id,为了完整性,在第一列加上-1,n是总数目
  5. void GetSet(int *si, int *fi, int i, int n)
  6. {
  7. int m = i + 1;
  8. while (m <= n && si[m] < fi[i])//找第一个符合的
  9. m = m + 1;
  10. if (m <= n)
  11. {
  12. cout << m << "\t";
  13. GetSet(si, fi, m, n);
  14. }
  15. }
  16. int main()
  17. {
  18. int si[] = { -1,1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12 };
  19. int fi[] = { -1,4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
  20. int n = 11;
  21. GetSet(si, fi, 0, 11);
  22. }

动态规划

  1. #include<iostream>
  2. using namespace std;
  3. //动态规划实现
  4. int GetSet(int *start, int *finish, int n)
  5. {
  6. //c[i][j]表示第i个工作结束后到第j个工作开始前之间存在的可兼容的工作个数
  7. //new c[i][j]
  8. int **c = new int *[n];
  9. for(int i=0; i<n; i++)
  10. c[i] = new int[n];
  11. //c[i][j]初始赋值
  12. for(i=0; i<n; i++)
  13. for(int j=0; j<n; j++)
  14. c[i][j] = 0;
  15. for(int j=0; j<n; j++)
  16. {
  17. for(i=0; i<n; i++)
  18. {
  19. if(i<j)
  20. {
  21. int s = finish[i];
  22. int f = start[j];
  23. for(int k=i+1; k<j; k++)
  24. if(start[k]>=s && finish[k]<=f)
  25. {
  26. if(c[i][j]<(c[i][k]+c[k][j]+1))
  27. c[i][j] = c[i][k]+c[k][j]+1; //分解成更小子问题
  28. }
  29. }
  30. }
  31. }
  32. return c[0][n-1]; //最终目标
  33. }
  34. int main()
  35. {
  36. //已经按完成时间排好序
  37. int start[] = {-1,3,0,5,3,5,6,8,8,2,1000};
  38. int finish[] = {0,5,6,7,8,9,10,11,12,13,10000};
  39. int n = 11; //活动只有9个
  40. cout<<"最大兼容活动子集的大小为:"<<GetSet(start, finish, n)<<endl;
  41. return 0;
  42. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注