有关约瑟夫问题小结
2015-05-13 12:07
260 查看
<span style="font-family: Verdana, Arial, 'BitStream vera Sans', Helvetica, sans-serif;"></span>循环链表有个典型应用就是解约瑟夫问题(Josephus),这里用的典型题目是"猴子选大王"。
问题描述:有m只猴子打算从中选出一个大王,但猴子们打斗三日,仍然选不出大王。后来经过协商,决定选大王的规则如下: 大家围成一圈,从1到m为每次猴子编号。然后从1开始报数, 数到n的出局。剩下的猴子再从1开始报数。最后剩下来的就是大王。有一只猴子很聪明(它就是猴精!)占据了一个位置,最后成为了大王。请编程计算一下,它占据是的哪个位置。 输入格式:一行,由空格分开的两个整数m n。 输出格式:一个整数,表示大王的编号 样例输入:15 3 样例输出:5 样例输入:200 55 样例输出:93 数据规模和约定:10000>m>0; 100>n>0;
C语言代码如下:
<span style="font-family: Verdana, Arial, 'BitStream vera Sans', Helvetica, sans-serif;">//</span>
// main.c // main // // Created by Apple on 15/5/13. // Copyright (c) 2015年 Apple. All rights reserved. // #include <stdio.h> int main(int argc, const char * argv[]) { int a[10000]; int m; int n; int x; int count; int i; scanf("%d",&m); scanf("%d",&n); for(i=1;i<=m;i++) a[i]=i; count=m; x=0; for(i=0;count>1;i++){ if(a[i%m+1]!=-1){ x++; } if(x==n && a[i%m+1]!=-1){ a[i%m+1]=-1; count--; x=0; } } for(i=1;i<=m;i++) if(a[i]!=-1) printf("%d\n",i); return 0; }
循环链表c语言实现:
// // main.c // main2 // // Created by Apple on 15/5/13. // Copyright (c) 2015年 Apple. All rights reserved. // #include <stdio.h> #include <stdlib.h> /* 定义链表节点类型 */ typedef struct node{ int data; struct node *next; }linklist; int main(int argc, const char * argv[]) { int i, n, k, m, total; linklist *head, *p, *s, *q; printf("请输入猴子的个数:"); /* 读入问题条件 */ scanf("%d", &n); printf("请输入要从第几个猴子开始报数:"); scanf("%d", &k); printf("请输入出局数字:"); scanf("%d", &m); head = (linklist*) malloc(sizeof(linklist)); /* 创建循环链表,头节点也存信息 */ p = head; p->data = 1; p->next = p; /* 初始化循环链表 */ for (i = 2; i <= n; i++){ s = (linklist*) malloc(sizeof(linklist)); s->data = i; s->next = p->next; p->next = s; p = p->next; } /* 找到第 k 个节点 */ p = head; for (i = 1; i < k; i++){ p = p->next; } /* 保存节点总数 */ total = n; printf("\n出局序列为:"); q = head; /* 只剩一个节点时停止循环 */ while (total != 1) { /* 报数过程,p指向要删除的节点 */ for (i = 1; i < m; i++) { p = p->next; } /* 打印要删除的节点序号 */ printf("[%d] ", p->data); /* q 指向 p 节点的前驱 */ while (q->next != p) { q = q->next; } /* 删除 p 节点 */ q->next = p->next; /* 保存被删除节点指针 */ s = p; /* p 指向被删除节点的后继 */ p = p->next; /* 释放被删除的节点 */ free(s); /* 节点个数减一 */ total--; } /* 打印最后剩下的节点序号 */ printf("\n\n猴子大王为第 [%d] 号\n\n", p->data); free(p); //system("pause"); return 0; }
只用数组方法:
// // main.c // main4 // // Created by Apple on 15/5/13. // Copyright (c) 2015年 Apple. All rights reserved. // #include <stdio.h> int choose(int n,int m); int n,m; /*n只猴子,报数m*/ int a[10000]; int main(int argc, const char * argv[]) { int m,n,p; scanf("%d %d",&n,&m); p=choose(n,m); printf("%d",p); getchar(); return 0; } int choose(int n,int m){ int i,sum=0,countOne=n; /*存剩余猴子数*/ for(i=0;i<n;i++) a[i]=1; i=0; while (i<=n){ if (i==n) i=0; /*当i=n时,循环回去*/ sum+=a[i]; if(sum==m) /*当报到m时 */{ sum=a[i]=0; /*淘汰倒霉猴子;即赋0 */ countOne--; /*剩余猴子数-1*/ if (countOne==1) break; /*剩1只时结束*/ } i++; } for(i=0;i<n;i++){ if(a[i]!=0) return i+1; /*找到猴子大王编号(从1开始的)*/ } return 0; }
最后一个算法是在网上看到的,我表示并不能看懂是什么意思,先放在这里吧。如果有哪个大神看懂了记得跟我讲解一下
//
// main.c
// main3
//
// Created by Apple on 15/5/13.
// Copyright (c) 2015年 Apple. All rights reserved.
//
#include <stdio.h>
const int M = 3;
int main(int argc, const char * argv[]) {
int n, s = 0;
scanf("%d", &n);
int i;
for (i = 2; i <= n; ++i)
s = (s+M)%i;
printf("%d\n", s+1);
return 0;
}
相关文章推荐
- php实现约瑟夫问题的方法小结
- 有关 jffs2_scan_eraseblock 问题小结
- 有关shell或linux问题小结
- 有关RP的table-layout以及表格文字溢出问题小结
- 有关 jffs2_scan_eraseblock 问题小结(转载)
- 有关问题小结(22)-代码实现logcat保存
- 约瑟夫问题例题小结
- 有关环形数组的约瑟夫问题
- 约瑟夫问题C++实现
- 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
- 面试中常被问到的有关进程、线程和网络的问题
- POJ-2746:约瑟夫问题(Java版)
- (7)约瑟夫问题
- 有关hibernate的几个面试问题
- 约瑟夫问题的链表实现
- sqlbox的有关问题
- 有关时间的问题
- 【Openjudge】约瑟夫问题
- 关于Java调用批处理命令向mysql导入数据的中文乱码有关问题
- 网办项目经验小结2-编码及form清除问题