约瑟夫环 HOJ 1016

来源:互联网 发布:java reference 编辑:程序博客网 时间:2024/06/09 18:59

                                          HOJ 1016 Joseph's problem

题目链接:点击打开链接
约瑟夫环N个囚犯站成一圈, 准备杀掉, 从第1个人开始越过 k-2个人,杀掉第K个人,  然后越过 k -1                          个人杀掉 这个过程沿着一个圆圈进行 最后只剩下一个人。。。
          最后那个人可以活着。给定 N k 问最后那个人能活着
            这英文不好确实很头疼啊,好伤心的有木有啊

题目大意:
            每次看题都好费劲,要是我能读英文比北京晚报还溜就好了。。。 这里每次从0开始报数
            是说 约瑟夫的侄子, 每杀掉 第m  个人 ,例如: 每次杀掉 第 m个 人 假设  m = 2
0123456789                                                   假设 k  = m%n    第一轮之后 只剩下 n-1 个人 从 k 开始报数 1. 2..3.... 
                                         原队列编号:            k + 1, k+2 ..........n-2      n-1 ,    1  2 .....k-1
                                         从k开始报数编号:   1       2      3                    n-1-k  n-k  ,n+1-k
先按照约瑟夫环走一遍 假设一共有10 个人 每次杀掉第二个人
 代码:
#include<cstdio>#include<cstdlib>#define M 2#define N 10#define START 0struct Linklist{    int data;    struct  Linklist *next;}LNode[N];typedef struct Linklist *link; //定义节点int main(){    link p, r;    for(int i = 0 ; i < N ; i++)    {        LNode[i].data = i + 1;        if(i < N-1)        {            LNode[i].next = &LNode[i+1];        }        else        {//最后一个指向首位置            LNode[i].next = LNode;        }    }    p = &LNode[START]; //p指向首位置节点    while(p->next != p)    {        //循环没有结束        for(int i = 1 ; i < M ; i++)        {//r 的作用就是用来记录最终节点盘p 在那个位置            r = p ;            p = p->next;        }        r->next  = p->next;        printf("第%d个人杀掉\n", p->data);        p = r->next;        //上面以及已经结束了约瑟夫环    }   return 0;}

结果很明显依次杀掉的人是 2 4 6 8 10 3 7 1 9
下面尝试其他方式进行求解:
数学归纳的思想:  每次删掉的是第 2 个人 那么 M = 2

所有最后剩下的就是    5 也就是说5 是幸存者
          
参考博客 :点击打开链接                       

。。。。。
                                                                               
初始:
12345678910
 1、第一轮之后是:  从1 开始 2除掉   第一轮之后  1 3456789 
  2、第二轮 从 3 开始数删掉的是4
1 3 56789103、第三轮 从6 开始 删掉的是6
1 3  5   7   8  9  10 4、第四轮 从7 开始 删掉的是8
1 3    5  7  9 105、第五轮从9开始删掉10 


代码:
#include<iostream>using namespace std;int main(){    int m , n;    int i ;    int s = 0;    cin>>n>>m;    for(i = 2 ; i <= n ; i++)    {        s = (s + m)%i;    }    cout<<s+1<<endl;    return 0;}


代码:
#include<cstdio>const int MAX = 32580;const int MAX_NUM = 3520;int main(){//约瑟夫环问题//问题描述 有n 个人做在一起    //下面首先用线性塞子判断素数并进行标记    bool prime[MAX] = { false };  //所有的数都设成false    int p[MAX_NUM];    //用来存放素数的    int n, i, j;    int  k = 0;    for(i = 2; i < MAX ; i++)    {       if(!prime[i])           p[k++] = i;       for(j = 0 ;j < k && i*p[j] < MAX; j++)       {           prime[i*p[j]] = true;           if(i%p[j]== 0)           {               break;           }       }       //至于上面的数字为什么要写成32580大概就是为了得到3520 个素数的    }    while(scanf("%d", &n) != EOF && n != 0)    {       //下面才是程序       int m = 0 ;       for(i = n-2 ; i >= 0 ; i--)       {           m = (m + p[i]) % (n-i);       }       printf("%d\n", m+1);    }    return 0;}



                   

0 0
原创粉丝点击