[关闭]
@dsy12138 2018-02-28T11:11:54.000000Z 字数 4827 阅读 389

算法 程序设计

封面

一些算法问题的汇总

  "You know nothing。" --《Game of Thrones》

N皇后问题

  这是源于国际象棋的一个问题。N-皇后问题要求在一个N*N格的棋盘上放置n个皇后,使得它们彼此不受攻击。按照国际象棋的规则,一个皇后可以攻击与之处于同一行或列或者一条斜线上的任何其他棋子。因此,N-皇后问题最后等价于要求在一个N*N格的棋盘上放置n个皇后,使得任何两个皇后不能被放在同一行或同一列或同一条对角线上。
  本题输入格式只有一个,输入一个n(1<=n<=10),以棋盘格式输出皇后(用字符Q表示)的位置。
-----------------------算法分析------------------------------
  本题的思想采用回溯法求解,回溯法在理论上可以解决一个问题的一个解或者N个解,代价是需要大量试错(这也就是为什么要使用贪心算法和分支限界法的原因)。不过,在走投无路的情况下,可能回溯法是一个比较好的选择吧。
  回溯法求解N皇后问题即遍历每一行,在每一行上放置一个棋子(皇后),然后判断是否满足条件,若满足则输出结果,若不满足,则回溯到上一行向右移放置至下一个位置,再进行条件判断。直到所有位置均被放置完毕。
  代码如下:

  1. #include <STDIO.H>
  2. #include <MATH.H>
  3. #define SIZE 100
  4. enum chess
  5. {
  6. QUEEN=81,
  7. BLANK=32
  8. };
  9. int X[SIZE];
  10. void printout(int length) //输出棋盘
  11. {
  12. printf("输出结果阵列:\n");
  13. for(int i=1;i<=length;i++) {
  14. for (int j=1;j<=length;j++)
  15. if(j==X[i])
  16. printf("%2c",QUEEN);
  17. else
  18. printf("%2c",BLANK);
  19. printf("\n");
  20. }
  21. printf("\n");
  22. }
  23. bool isPlace(int k) //是否可以摆放
  24. {
  25. for(int i=1;i<k;i++)
  26. if(X[i]==X[k]||abs(X[i]-X[k])==abs(i-k))
  27. return false;
  28. return true;
  29. }
  30. void findQueen(int n) //回溯法搜寻可能结果
  31. {
  32. X[1]=0;
  33. int k=1;
  34. while(k>0)
  35. {
  36. X[k]++;
  37. while(X[k]<=n&&!isPlace(k))X[k]++;
  38. if(X[k]<=n) {
  39. if(k==n)
  40. printout(n);
  41. else {
  42. k++;
  43. X[k]=0;
  44. }
  45. } else
  46. k--;
  47. }
  48. }
  49. void main()
  50. {
  51. int n;
  52. printf("请输入棋盘的长宽N:");
  53. scanf("%d",&n);
  54. findQueen(n);
  55. }

程序大致效果如下:

类找零问题

  我们班最近也要开始填写素质拓展分了,我们的团支说由于我们学校的DB丢失备份了,导致所有学生参加的活动都不能确认了,但是总分是知道的。比如,知道XX同学的大二学年的素质拓展总分为10.4分,那么你可以在所有的活动中任意挑选活动,总之,只要加起来的总分等于素质拓展分总分就行。有许多活动有着相同的得分,以及相同分数的活动的数目都是有限的。
----------------------问题的数学描述--------------------------
  已知有集合 ;
产生一个挑选集合;
使得且满足

------------------------算法分析-----------------------------------
  本题可以采用贪心算法或者回溯法来求解,使用回溯法可以看到所有的解的结果。本题选择采用回溯法求解问题。第一个结果即为贪心算法求得的结果,若要得到贪心算法的最优结果,活动集合必须按照得分从大到小排列。
回溯体的伪代码描述如下:
BackTrace(解空间序号 t)
  if t > 解空间长度
    if
      输出解决方案;
    endif
  else
    for i:Nt to 1 step -1
      解空间向量t:=i;
      if
        BackTrace(t+1);
      endif
      解空间向量t:=0;
    endfor
  BackTrace(t+1);
  endif
end

Selection.h

  1. #ifndef _SELECTION_H
  2. #define _SELECTION_H
  3. #define UINT unsigned int
  4. #define EQUAL 0.0001
  5. #define SIZE 100
  6. #include <iostream.h>
  7. #include <fstream.h>
  8. #include <assert.h>
  9. #include <stdlib.h>
  10. #include <math.h>
  11. typedef struct
  12. {
  13. int number;
  14. double score;
  15. }Relation;
  16. class Selection
  17. {
  18. private:
  19. UINT *x;
  20. Relation *r;
  21. int Length;
  22. double Score;
  23. void Calculate(int t);
  24. bool OK(int t);
  25. public:
  26. Selection(char *FName);
  27. void Excute(double Your_Score);
  28. void Close();
  29. };
  30. #endif

Selection.cpp

  1. #include "Selection.h"
  2. Selection::Selection(char *FName)
  3. {
  4. int i=0;
  5. r=new Relation[SIZE];
  6. //Read Data from Text
  7. ifstream inFile;
  8. inFile.open(FName,ios::in|ios::nocreate);
  9. assert(inFile!=NULL);
  10. while(!inFile.eof())
  11. {
  12. inFile>>r[i].number;
  13. inFile>>r[i].score;
  14. i++;
  15. assert(i<=SIZE);
  16. }
  17. inFile.close();
  18. //Init the Parameters
  19. Length=i;
  20. };
  21. bool Selection::OK(int t)
  22. {
  23. double sum=0;
  24. for(int k=0;k<=t;k++)
  25. sum+=x[k]*r[k].score;
  26. if(sum>Score)
  27. return false;
  28. return true;
  29. };
  30. void Selection::Calculate(int t)
  31. {
  32. if(t>Length)
  33. {
  34. double Sum=0;
  35. for(int k=0;k<Length;k++)
  36. Sum+=x[k] * r[k].score;
  37. if(fabs(Score-Sum)<=EQUAL)
  38. {
  39. cout<<"Result:"<<endl;
  40. for(int k=0;k<Length;k++)
  41. if(x[k]!=0)cout<<x[k]<<":"<<r[k].score<<endl;
  42. cout<<endl;
  43. }
  44. }
  45. else
  46. {
  47. for(int j=r[t].number;j>=1;j--)
  48. {
  49. x[t]=j;
  50. if(OK(t))Calculate(t+1);
  51. x[t]=0;
  52. }
  53. Calculate(t+1);
  54. }
  55. };
  56. void Selection::Excute(double Your_Score)
  57. {
  58. Score=Your_Score;
  59. x=new UINT[Length];
  60. for(int i=0;i<Length;i++)x[i]=0;
  61. Calculate(0);
  62. delete []x;
  63. };
  64. void Selection::Close()
  65. {
  66. delete []r;
  67. };

MainActivity.cpp

  1. #include "Selection.h"
  2. void main()
  3. {
  4. double score;
  5. cout<<"Please input a score:"<<endl;
  6. cin>>score;
  7. Selection *select=new Selection("in.txt");
  8. select->Excute(score);
  9. select->Close();
  10. }

数据集

活动名称 学分
廉洁修身立志成才演讲内部选拔赛 0.6
巢湖学院棋队选拔赛 0.6
青春中国朗诵比赛 0.6
巢湖学院第二届廉洁修身立志成才演讲比赛校级 1.0
排队周 0.6
诚信考试活动 0.6
放飞心灵,激扬青春主题征文比赛 0.6
心理健康教育系列讲座 0.6
文传系征文大赛系内选拔 0.6
计算机学院"学团史、知团情、跟党走"大学生知识竞赛 0.6
经管法学习"两代会"精神 0.6
历史旅游文化系"廉洁修身,立志成才"大学生演讲比赛 0.6
历史旅游文化系"学党史、知团情、跟党走"知识竞赛 0.6
体育系心理演讲座谈会 0.6
艺术学院演讲比赛 0.6
艺术学院团史知识竞答 0.6
自动化学院大学生心理健康讲座 0.6
巢湖学院第二届"廉洁修身,立志成才"演讲比赛 0.6
绿色骑行扶贫行动 0.6
绿色典当 0.6
小学生环境教育 0.6
去巢湖司巷小学探望留守儿童 0.6
消防日 0.6
迎接两代会校园清扫活动 1.0
敬老院之行 0.6
微博图文大赛宣传 0.6
世界问候日 0.6
博爱在江淮,益起进社区,角膜捐献进校园 0.6
特教之行 0.6
合肥市国际志愿者日暨"三线三边"环境整治志愿服务启动仪式 0.6
巢湖市交通志愿引导服务工作 0.6
阳关计划暖暖冬衣行 0.6
"大手牵小手"传递爱心关爱未来 0.6
"让巢湖生活更美好"防尘防雾霾环保宣传活动 0.6
艺术学院消防日活动 0.6
艺术学院职业规划大赛 0.6
巢湖学院第二届三行诗征诗大赛 0.6
逐日创作社报纸 0.6
雷雨话剧社专场演出 1.0
主题文艺晚会 0.6
绿色之旅巢湖龟山轮滑行 0.6
汤山动漫社特色画展活动 0.6
暖冬围巾设计与编织活动 0.6
短剧PK 0.6
时光台球室比赛 0.6
第一届巢湖学院台球比赛 0.6
模拟考试之英语四级模考 0.6
三大社团文学讲座 0.6
去榕树心理咨询中心 0.6
巢湖学院第十届宿舍文化节 1.2
巢湖学院第四届大学生辩论赛 1.0
公益创新活动大 0.6
"今天,说说你的心里话"活动 0.6
"心理咨询进社区"活动 0.6
"我与学生会"PPT演讲大赛 0.6
辩论赛 0.6
首届汉字听写大赛 0.6
《大学女生》杂志 0.6
首届羽毛球联赛 0.6
首届乒乓球联赛 0.6
巧手巧心手工艺品制作大赛 0.6
"爱我巢湖,环保进行时"活动 0.6
"青春志,中国梦"大型主题团日活动 0.6
第八届昆山花轿杯职业规划大赛系类选拔 0.6
文传系迎新杯篮球赛 0.6
文传系迎新晚会 0.6
数学系第二届妆容礼仪大赛 0.6
艺术学院展板设计大赛 0.6
台球协会台球教程活动 0.6
营销知识讲座 0.6
第一届非赞不可英语歌曲大赛 0.6
UEA英语四级模拟考试 0.6
演讲朗诵辩论讲座 0.6
优秀青年志愿者培训班 0.6
计算机知识技能系列比赛 0.6
数学系新生演讲比赛 0.6
计算机学院"廉洁修身,立志成才"大学生演讲比赛 0.6

in.txt

活动数目 分数
5 1.2
4 1
20 0.6
7 0.2

程序运行效果如下:

------------------------程序或算法的不足----------------------------
  问题:不能按照答案得到相应的活动名称序列。
  解决办法:可以再增加一个数组读入所有活动序列,然后根据上述程序的运行结果随机匹配活动名称。由于时间的关系,就不再深入了。当然也还有其他可以改良的地方。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注