约瑟夫环 HOJ 1016

                                          HOJ 1016 Joseph's problem

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

题目大意:
            每次看题都好费劲,要是我能读英文比北京晚报还溜就好了。。。 这里每次从0开始报数
            是说 约瑟夫的侄子, 每杀掉 第m  个人 ,例如: 每次杀掉 第 m个 人 假设  m = 2
0 1 2 3 4 5 6 7 8 9
                                                   假设 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
#include

#define M 2
#define N 10
#define START 0

struct 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 是幸存者
          
参考博客 :点击打开链接                       

。。。。。
                                                                                
初始:
1 2 3 4 5 6 7 8 9 10

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


代码:
#include
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<


代码:
#include

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;
}



                   

再提供一种环都解决方法:

/**
 * 类说明
 * 
 * 
 * Modify Information:
 * Author        Date          Description
 * ============ =========== ============================
 * DELL          2017年3月31日    Create this file
 * 
* */ public class ListHasCycle { /** * @param args */ public static boolean hasCycle(ListNode head) { /* * 判断一个链表中是否有环 * 1. 快慢指针的方式 * 1->2->3->4->5>6->7 * * 5<-8-<9-< * 5 6 7 8 9 5 再回到5 这个就是有环的 这个 环有一定规则的 * 怎样判断出这个环 一个速度是另外速度的两倍就可以 */ if(head == null) return false; ListNode fast = head; ListNode slow = head; while((fast != null) && (fast.next != null) ){ slow = slow.next; fast = fast.next.next; if(fast == slow){ return true; } } return false; } public static void main(String[] args) { // TODO Auto-generated method stub ListNode node1 = new ListNode(5); ListNode node2 = new ListNode(6); ListNode node3 = new ListNode(7); ListNode node4 = new ListNode(8); ListNode node5 = new ListNode(9); node1.next = node2; node2.next = node3; node3.next = node4; node4.next = node5; node5.next = node1; boolean ans = hasCycle(node1); System.out.println(ans); } }



你可能感兴趣的:(约瑟夫环 HOJ 1016)