实质上是将所有人按编号入队,当数到三时此人直接出队,表示已经死亡,同时将k置为1,表示重新计数。其他时候将该人先出队后入队即可,表示进入新的一轮,直至队列元素为1结束。
采用循环队列,循环结束标志为:
Q -> rear != (Q - >front + 1) % 100
即只剩下一个元素的时候
源代码 #include解法二:数组解法#include typedef struct { int *data; int front,rear; int queuesize; int length; }Queue; void Init (Queue *Q) //构造一个队列 { Q->queuesize = 100; Q->data = (int *)malloc(Q->queuesize*sizeof(int)); Q->front = Q->rear = 0; Q->length = 0; } void build (Queue *Q) //为队列赋值 { int i; for(i=1;i<=41;i++) { Q->data[Q->rear] = i; Q->length++; Q->rear = (Q->rear+1)%100; } //printf("n------%d-----n",Q->length); Q->front = 0; } void EnQue (Queue *Q,int e) //入队 { if((Q->rear+1)%100 != Q->front) { Q->data[Q->rear] = e; Q->rear = (Q->rear+1)%100; } } void OutQue(Queue *Q) //出队 { if(Q->rear != Q->front) { Q->front = (Q->front+1)%100; } } void display(Queue *Q) { if(Q->rear != Q->front) { printf("%d ",Q->data[Q->front]); Q->front = (Q->front+1)%100; } } void yuesefu(Queue *Q) { int k=1,e; while(Q->rear!=(Q->front + 1)%100) { e = Q->data[Q->front]; if(k == 3) { display(Q); k = 1; Q->length--; } else { OutQue(Q); EnQue(Q,e); k++; } } printf("n最后剩下:%d", Q->data[Q->front]); } int main() { Queue Q; Init(&Q); build(&Q); yuesefu(&Q); return 0; }
本质上就是一个伪链表,用一个数组arr[]表示编号人员的状态,t代表死亡人数,每个人都遍历一次,从i = 0开始遍历,若arr[i] = 0, 说明人没死,计数cnt + 1, 当计数到3时,将
arr[i] = 1 ; 代表该人已经死亡
t++; 代表死亡人数+1
cnt = 0; 重新计数
当所有人遍历完后输出最后一个人即可。
源代码#include解法三:循环链表using namespace std; int main(){ int n = 41,m = 3; bool arr[n+1]; for(int i = 0; i <= n + 1; i++)arr[i] = 0; int t = 0,cnt = 0,i = 0; while(t < n){ i++; if(i>n) i=1; if(!arr[i]) cnt++; if(cnt==m){ cnt=0; t++; arr[i]=1; if(t == n){ printf("n最后剩下:%d", i); }else{ printf("%d ",i); } } } return 0; }
循环链表可以更加简洁明了地描述约瑟夫环,创建一个41号元素的循环链表,从第一位开始遍历。 当数到三的前一位时,用temp指向自杀人结点
temp = p -> next;
直接由第i-1位指向第i+1位
p -> next=temp->next;
最后删除temp结点
free(temp);
最后将总人数-1,重复过程直至n == 1。
源代码#include解法四:一步求解#include #include #include using namespace std; int n; typedef struct node{ //循坏链表 int date; struct node *next; }node,*linklist; linklist creat(int n){ //循坏链表初始化 linklist p,head; head=(linklist)malloc(sizeof(node));//建立头结点 p=head; linklist s; int i=1; if(n!=0) { while(i<=n) { s=(linklist)malloc(sizeof(node)); s->date=i++; p->next=s; p=s; } s->next=head->next; //尾节点跳过头结点直接指向第一个元素地结点 } free(head); //删除头结点 return s->next; } int main() { n = 41; int m=3; int i; linklist p=creat(n); linklist temp; m%=n; while(n > 1) { for(i=1;i next; } printf("%d->",p->next->date); temp=p->next; p->next=temp->next; //模拟约瑟夫环的淘汰过程 free(temp); p=p->next; n--; } printf("n"); linklist h = p; printf("最后剩下:%d ", p -> date); return 0; }
如果只是求最后存活的人编号的化, 有如下公式:
p = (p+m) % i;
源代码
#includeusing namespace std; int main(){ int n = 41,m = 3; int p=0; for(int i=2;i<=n;i++)p=(p+m)%i; printf("最后活着的人的编号为%dn",p+1); }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)