敢死队问题(借助公式)
2016-12-23 10:44
288 查看
问题描述
问题描述:有M(M>10)个敢死队员要炸掉敌人的一碉堡,谁都不想去,排长决定用轮回数数的办法来决定哪个战士去执行任务。如果前一个战士没完成任务,则要再派一个战士上去。现给每个战士编一个号,大家围坐成一圈,随便从某一个战士开始计数,当数到8时,对应的战士就去执行任务,且此战士不再参加下一轮计数。如果此战士没完成任务,再从下一个战士开始数数,被数到第8时,此战士接着去执行任务。以此类推,直到任务完成为止。
排长是不愿意去的,假设排长为最后第M号,请你设计一程序,求出从第几号战士开始计数才能让排长最后一个留下来而不去执行任务。
分析
我的上篇文章(http://blog.csdn.net/hg_zhh/article/details/53819791)讲述了,一般见到此问题的思路:从每个人开始,都数一次,当最后剩下的人是排长时,输出,如果中途排长被数到,则跳出,尝试从下一个人数.
然而这种暴力求解的方式在m略大的情况时,时间和空间复杂度都不乐观.通过尝试不难发现. 如果假设从第一个人开始数,最后一个剩下的序号记为temp;总人数有m,则得出一个公式answer=(m-temp+1)%m;
而answer即为题目所求的结果;
此公式我是利用下图计算得出的:
从其中不难发现从第几个开始数,与最后剩余的是第几个,这两个变量间是存在线性关系的,只需加以推导就能得出。
下面这个代码与我上次上传的有些许差异,主要在于本次代码,只需要初始化一次链表结构即可。
代码实现
总结:
此类问题,关键在于得出一般公式。诸位可以尝试排长排在第a个位置的情况(我还没尝试过)。
问题描述:有M(M>10)个敢死队员要炸掉敌人的一碉堡,谁都不想去,排长决定用轮回数数的办法来决定哪个战士去执行任务。如果前一个战士没完成任务,则要再派一个战士上去。现给每个战士编一个号,大家围坐成一圈,随便从某一个战士开始计数,当数到8时,对应的战士就去执行任务,且此战士不再参加下一轮计数。如果此战士没完成任务,再从下一个战士开始数数,被数到第8时,此战士接着去执行任务。以此类推,直到任务完成为止。
排长是不愿意去的,假设排长为最后第M号,请你设计一程序,求出从第几号战士开始计数才能让排长最后一个留下来而不去执行任务。
分析
我的上篇文章(http://blog.csdn.net/hg_zhh/article/details/53819791)讲述了,一般见到此问题的思路:从每个人开始,都数一次,当最后剩下的人是排长时,输出,如果中途排长被数到,则跳出,尝试从下一个人数.
然而这种暴力求解的方式在m略大的情况时,时间和空间复杂度都不乐观.通过尝试不难发现. 如果假设从第一个人开始数,最后一个剩下的序号记为temp;总人数有m,则得出一个公式answer=(m-temp+1)%m;
而answer即为题目所求的结果;
此公式我是利用下图计算得出的:
从其中不难发现从第几个开始数,与最后剩余的是第几个,这两个变量间是存在线性关系的,只需加以推导就能得出。
下面这个代码与我上次上传的有些许差异,主要在于本次代码,只需要初始化一次链表结构即可。
代码实现
#include<stdio.h> #include<malloc.h> struct List { int data; struct List *next; }; struct List * CreatList ()//建立空链表 { struct List *L; L=(struct List *)malloc(sizeof(struct List)); if (L==NULL) { printf("内存分配失败\n"); exit(0); } L->next=NULL; return L; } void InitList (struct List *L,int n)//将L初始化为无 头结点的链表 { struct List *P,*T ; int i; T=L; T->data=1; T->next=NULL; for ( i=2;i<=n;i++) { P=(struct List *)malloc(sizeof(struct List ));//申请空间 if (P==NULL)// 如果不成功,则退出程序 { printf("内存分配失败\n"); exit(0); } P->data=i; P->next=NULL; T->next=P; T=P; } P->next=L; } int deleteNode(int m)//假设从第一个人开始数时,返回最后一个出去的人的序号 { struct List *L,*temp,*p; L=CreatList(); InitList(L,m); p=L; int i,j; for (j=0;j<m-1;j++) { for (i=1;i<8-1;i++) { p=p->next; } temp=p->next; p->next=temp->next; free(temp); p=p->next; } return p->data; } void answer () { int m; printf("共有多少人、\n"); scanf("%d",&m); int num=deleteNode(m); int temp=(m-num+1)%m;//此公式是此程序最关键的地方 printf("从第%d个数\n",temp); } int main() { answer(); return 0; }
总结:
此类问题,关键在于得出一般公式。诸位可以尝试排长排在第a个位置的情况(我还没尝试过)。
相关文章推荐
- 水晶报表公式求和问题
- 如何解决数学软件Maple v9.5在中文Windows下,公式输入中光标定位错误的问题
- aurora在word中插入公式时会卡住的问题
- C# 导出Excel 中设置公式、格式问题
- 关于Excel公式引用公式导致结果异常的问题
- 数据结构(c语言版)清华大学出版社,的几个公式问题
- word2010的公式编辑功能和问题缺陷
- 关于POI操作excel中带公式的的单元格问题
- 关于EXCEL中公式复制后不自动计算的问题!
- 关于 贝叶斯 计算公式的一个问题
- excel VBA 公式计算结果引用问题
- Poi处理Excel时公式不能更新的问题
- crystal report 2008 公式字段问题
- excel 复制公式计算结果问题的解决方法
- 用程序给生成的Excel中添加公式时注意的问题.
- 物理方法解决数学问题(二):Archimedes与球体积公式
- 关于表间公式的问题-补充明细为什么失效了
- Latex 公式中换行问题
- Latex带括号的多行公式问题(转)
- EXCEL VBA 公式计算问题小结