zoukankan      html  css  js  c++  java
  • 双向约瑟夫问题

    本题被归于线性表章节。

      约瑟夫问题是一个经典的问题,我们不妨将这个经典问题进行扩展,变成一个双向的约瑟夫问题。

      已知 n 个人(不妨分别以编号 1,2,3,...,n 代表 )围坐在一张圆桌周围,首先从编号为 k 的人从 1 开始顺时针报数,1, 2, 3, ...,记下顺时针数到 m 的那个人,同时从编号为 k 的人开始逆时针报数,1, 2, 3, ...,数到 m 后,两个人同时出列。然后从出列的下一个人又从 1 开始继续进行双向报数,数到 m 的那两个人同时出列,...;。依此重复下去,直到圆桌周围的人全部出列。直到圆桌周围只剩一个人为止。

      如果双向报数报到 m 时落在同一个人身上,那本次出列的只有一个人。

      例如:5,1,2。则总共5个人,从1开始顺时针报数,数到2,定位编号2;同时从1开始报数数到2,定位编号5;2和5同时出列。然后继续开始报数,顺时针报数3,4,定位到4;逆时针报数4,3,定位3;4和3同时出列。最后剩余的为编号1。输出为:2-5,4-3,1,。

      如果输入:6,2,3。则输出:4-6,2,1-3,5,。其中第2次只输出一个2,表示第二次双向报数时,恰好都落在编号2上,所以只有一个编号出列。

    输入:

    n,k,m

    输出:

    按照出列的顺序依次输出编号。同时出列编号中间用减号"-”连接。

    非法输入的对应输出如下

    a)

    输入:n、k、m任一个为0
    输出:n,m,k must bigger than 0.

    b)

    输入:k>n
    输出:k should not bigger than n.

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node
    {
        int No;
        struct node * next, * prev;
    }N, *PN;
    
    int main()
    {
        int n, k, m, i, j, start = 1;
        PN head, tmp, p = NULL, q = NULL;
        head = (PN)malloc(sizeof(N));
        head->next = head->prev = NULL;
        scanf("%d",&n);
        getchar();
        scanf("%d",&k);
        getchar();
        scanf("%d",&m);
    
        if (n<1 || k<1 || m<1)
        {
            printf("n,m,k must bigger than 0.
    ");
            return 0;
        }
        if (k>n)
        {
            printf("k should not bigger than n.
    ");
            return 0;
        }
        for (i=0; i<n; i++)
        {
            tmp = (PN)malloc(sizeof(N));
            if (i==0) q = tmp;
            if (head->next) head->next->prev = tmp;
            tmp->next = head->next;
            head->next = tmp;
            tmp->No = n-i;
            if (tmp->No == k)
                p = tmp;
        }
        q->next = head->next;
        q->next->prev = q;
        q = p;
        j = n;
        while (n--)
        {
            for (i=start; i<m; i++)
            {
                p = p->next;
                if (p->No == 0)
                    i--;
            }
            for (i=start; i<m; i++)
            {
                q = q->prev;
                if (q->No == 0)
                    i--;
            }
            printf("%d",p->No);
            p->No = 0;
            if (q != p)
            {
                printf("-%d", q->No);
                q->No = 0;
                n--;
            }
            start = 0;
            printf(",");    
        }
        printf("
    ");
        for (i=0; i<j; i++)
        {
            p = head->next;
            head->next = p->next;
            free(p);
        }
        free(head);
        return 0;
    }

      双向链表做的话,两个指针同时释放的情况有点多,容易造成重复释放,导致异常中断,所以在出队操作中只是修改其No域作为标记,循环结束后同一释放变量。

  • 相关阅读:
    POJ 3710 Christmas Game#经典图SG博弈
    POJ 2599 A funny game#树形SG(DFS实现)
    POJ 2425 A Chess Game#树形SG
    LeetCode Array Easy 122. Best Time to Buy and Sell Stock II
    LeetCode Array Easy121. Best Time to Buy and Sell Stock
    LeetCode Array Easy 119. Pascal's Triangle II
    LeetCode Array Easy 118. Pascal's Triangle
    LeetCode Array Easy 88. Merge Sorted Array
    ASP.NET MVC 学习笔记之 MVC + EF中的EO DTO ViewModel
    ASP.NET MVC 学习笔记之面向切面编程与过滤器
  • 原文地址:https://www.cnblogs.com/weir007/p/5977264.html
Copyright © 2011-2022 走看看