敢死队问题
2016-12-22 20:41
148 查看
问题描述:
有M(M>10)个敢死队员要炸掉敌人的一碉堡,谁都不想去,排长决定用轮回数数的办法来决定哪个战士去执行任务。如果前一个战士没完成任务,则要再派一个战士上去。现给每个战士编一个号,大家围坐成一圈,随便从某一个战士开始计数,当数到8时,对应的战士就去执行任务,且此战士不再参加下一轮计数。如果此战士没完成任务,再从下一个战士开始数数,被数到第8时,此战士接着去执行任务。以此类推,直到任务完成为止。
排长是不愿意去的,假设排长为最后第M号,请你设计一程序,求出从第几号战士开始计数才能让排长最后一个留下来而不去执行任务。
分析
本题类似于经典的约瑟夫问题,不过是有结果推出条件。在题目中,要使得排长最后一次执行任务,即他是最后剩余的人,则需要依次遍历从第一个人到最后一个人的情况。使用循环。
此程序使用的简单的for循环,但是当m很大时,花费的时间会很长。因此不是用于m很大的情况。
有M(M>10)个敢死队员要炸掉敌人的一碉堡,谁都不想去,排长决定用轮回数数的办法来决定哪个战士去执行任务。如果前一个战士没完成任务,则要再派一个战士上去。现给每个战士编一个号,大家围坐成一圈,随便从某一个战士开始计数,当数到8时,对应的战士就去执行任务,且此战士不再参加下一轮计数。如果此战士没完成任务,再从下一个战士开始数数,被数到第8时,此战士接着去执行任务。以此类推,直到任务完成为止。
排长是不愿意去的,假设排长为最后第M号,请你设计一程序,求出从第几号战士开始计数才能让排长最后一个留下来而不去执行任务。
分析
本题类似于经典的约瑟夫问题,不过是有结果推出条件。在题目中,要使得排长最后一次执行任务,即他是最后剩余的人,则需要依次遍历从第一个人到最后一个人的情况。使用循环。
//敢死队问题 2016 12 22 #include<stdio.h> #include<malloc.h> #include<stdlib.h> #include<stdbool.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; } bool deleteNode(int m,int n) { struct List *L,*p,*t; L=CreatList();//由于在删除节点的时候,会破坏数据个原本的结构,所以每一次在函数里初始化 InitList(L,m); p=L; int i,j; while(--n)//将指针p移动到开始数的地方 { p=p->next; } for (j=0;j<m-1;j++)//最多需要移除m-1个人 { for (i=1;i<7;i++)//将p移动到待移除人的前一个位置 { p=p->next; } if (p->next->data==m)//如果要一处的人是排长,则返回假 { return false; } else//否则,将该人移除 { t= p->next; p->next=t->next; p=p->next;//并从下一个人开始数 free(t); } } return true;//如果只剩排长一人 ,返回真 } void answer() { int m,n; printf("输入总人数\n"); scanf("%d",&m); for (n=1;n<=m;n++) { if (deleteNode(m,n)==true) printf("从第%d个数\n ",n); } } int main() { answer(); return 0; }
此程序使用的简单的for循环,但是当m很大时,花费的时间会很长。因此不是用于m很大的情况。