最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解約瑟夫環(huán)問題及其相關(guān)的C語言算法實(shí)現(xiàn)

 更新時(shí)間:2015年08月15日 11:59:01   作者:低調(diào)小一  
這篇文章主要介紹了詳解約瑟夫環(huán)問題及其相關(guān)的C語言算法實(shí)現(xiàn),也是ACM當(dāng)中經(jīng)常會(huì)引用到的基礎(chǔ)題目,文中共介紹了三種C語言解答,需要的朋友可以參考下

約瑟夫環(huán)問題

N個(gè)人圍成一圈順序編號(hào),從1號(hào)開始按1、2、3......順序報(bào)數(shù),報(bào)p者退出圈外,其余的人再從1、2、3開始報(bào)數(shù),報(bào)p的人再退出圈外,以此類推。  
請(qǐng)按退出順序輸出每個(gè)退出人的原序號(hào) 


算法思想
用數(shù)學(xué)歸納法遞推。

無論是用鏈表實(shí)現(xiàn)還是用數(shù)組實(shí)現(xiàn)都有一個(gè)共同點(diǎn):要模擬整個(gè)游戲過程,不僅程序?qū)懫饋肀容^煩,而且時(shí)間復(fù)雜度高達(dá)O(nm),若nm非常大,無法在短時(shí)間內(nèi)計(jì)算出結(jié)果。我們注意到原問題僅僅是要求出最后的勝利者的序號(hào),而不是要讀者模擬整個(gè)過程。因此如果要追求效率,就要打破常規(guī),實(shí)施一點(diǎn)數(shù)學(xué)策略。

為了討論方便,先把問題稍微改變一下,并不影響原意:
問題描述:n個(gè)人(編號(hào)0~(n-1)),從0開始報(bào)數(shù),報(bào)到(m-1)的退出,剩下的人繼續(xù)從0開始報(bào)數(shù)。求勝利者的編號(hào)。

我們知道第一個(gè)人(編號(hào)一定是m%n-1) 出列之后,剩下的n-1個(gè)人組成了一個(gè)新的約瑟夫環(huán)(以編號(hào)為k=m%n的人開始):
k k+1 k+2 ... n-2, n-1, 0, 1, 2, ... k-2并且從k開始報(bào)0。
現(xiàn)在我們把他們的編號(hào)做一下轉(zhuǎn)換:

k     --> 0
k+1   --> 1
k+2   --> 2
...
...
k-2   --> n-2
k-1   --> n-1
變換后就完完全全成為了(n-1)個(gè)人報(bào)數(shù)的子問題,假如我們知道這個(gè)子問題的解:例如x是最終的勝利者,那么根據(jù)上面這個(gè)表把這個(gè)x變回去不剛好就是n個(gè)人情況的解嗎??。∽兓厝サ墓胶芎唵?,相信大家都可以推出來:x'=(x+k)%n

如何知道(n-1)個(gè)人報(bào)數(shù)的問題的解?對(duì),只要知道(n-2)個(gè)人的解就行了。(n-2)個(gè)人的解呢?當(dāng)然是先求(n-3)的情況——這顯然就是一個(gè)倒推問題!好了,思路出來了,下面寫遞推公式:

令f[i]表示i個(gè)人玩游戲報(bào)m退出最后勝利者的編號(hào),最后的結(jié)果自然是f[n]

遞推公式
f[1]=0;
f[i]=(f[i-1]+m)%i; (i>1)

實(shí)現(xiàn)方法


一、循環(huán)鏈表
建立一個(gè)有N個(gè)元素的循環(huán)鏈表,然后從鏈表頭開始遍歷并計(jì)數(shù),如果基數(shù)i == m,則踢出該元素,繼續(xù)循環(huán),直到當(dāng)前元素與下一個(gè)元素相同時(shí)退出循環(huán)

    

#include <stdio.h> 
  #include <stdlib.h> 
  #include <string.h> 
    
  typedef struct lnode 
  { 
    int pos; 
    struct lnode *next; 
  } lnode; 
    
    
  /** 
   * 構(gòu)建循環(huán)鏈表&&循環(huán)遍歷 
   */ 
  void create_ring(lnode **root, int loc, int n) 
  { 
    lnode *pre, *current, *new; 
    current = *root; 
    pre = NULL; 
    
    while (current != NULL) { 
      pre = current; 
      current = current->next; 
    } 
    
    new = (lnode *)malloc(sizeof(lnode)); 
    new->pos = loc; 
    new->next = current; 
    
    if (pre == NULL) { 
      *root = new; 
    } else { 
      pre->next = new; 
    } 
    
    // 循環(huán)鏈表 
    if (loc == n) { 
      new->next = *root; 
    } 
  } 
    
  /** 
   * 約瑟夫環(huán) 
   */ 
  void kickoff_ring(lnode *head, int p) 
  { 
    int i; 
    lnode *pre, *pcur; 
    pre = pcur = head; 
    
    while (pcur->next != pcur) { 
      for (i = 1; i < p; i ++) { 
        pre = pcur; 
        pcur = pcur->next; 
      } 
    
      printf("%d ", pcur->pos); 
      pre->next = pcur->next; 
      free(pcur); 
      pcur = pre->next; 
    } 
    printf("%d\n", pcur->pos); 
    free(pcur); 
  } 
    
    
  void print_ring(lnode *head) 
  { 
    lnode *cur;  
    cur = head; 
    
    while (cur->next != head) { 
      printf("%d ", cur->pos); 
      cur = cur->next; 
    } 
    printf("%d\n", cur->pos); 
  } 
    
  int main() 
  { 
    int i, p, n; 
    lnode *head; 
    
    while (scanf("%d %d", &n, &p) != EOF) { 
      // 構(gòu)建循環(huán)鏈表 
      for (i = 1, head = NULL; i <= n; i ++) 
        create_ring(&head, i, n); 
    
      // 約瑟夫環(huán) 
      if (p != 1)  
        kickoff_ring(head, p); 
      else 
        print_ring(head); 
    } 
    
    return 0; 
  } 

    /**************************************************************
        Problem: 1188
        User: wangzhengyi
        Language: C
        Result: Accepted
        Time:110 ms
        Memory:912 kb
    ****************************************************************/ 

二、數(shù)組模擬
思想跟循環(huán)鏈表類似,少了構(gòu)建循環(huán)鏈表的過程

   

 #include <stdio.h> 
  #include <stdlib.h> 
   
  int main() 
  { 
    int i, index, p, n, remain, delete[3001], flag[3001] = {0}; 
   
    while (scanf("%d %d", &n, &p) != EOF) { 
      remain = n; 
      index = 0; 
      while (remain >= 1) { 
        for (i = 0; i < n; i ++) { 
          if (flag[i] == 0) { 
            // 報(bào)數(shù) 
            index ++; 
            // 報(bào)p者退出圈外 
            if (index == p) { 
              // 退出圈外 
              flag[i] = 1; 
              // 重新報(bào)數(shù) 
              index = 0; 
              delete[remain - 1] = i + 1; 
              remain --; 
            }   
          }   
        } 
      } 
   
      // 輸出每個(gè)退出人的序號(hào) 
      for (i = n - 1; i >= 0; i --) { 
        if (i == 0) { 
          printf("%d\n", delete[i]); 
        } else { 
          printf("%d ", delete[i]); 
        } 
      } 
    } 
   
    return 0; 
  } 

    三、數(shù)學(xué)推導(dǎo)
       

#include <stdio.h> 
   
  int main(void) 
  { 
    int i, n, m, last; 
   
    while (scanf("%d", &n) != EOF && n != 0) { 
      // 接收?qǐng)?bào)數(shù) 
      scanf("%d", &m); 
   
      // 約瑟夫環(huán)問題 
      for (i = 2, last = 0; i <= n; i ++) { 
        last = (last + m) % i; 
      } 
      printf("%d\n", last + 1); 
    } 
   
    return 0; 
  } 

相關(guān)文章

  • C語言float內(nèi)存布局示例詳解

    C語言float內(nèi)存布局示例詳解

    這篇文章主要為大家介紹了C語言float內(nèi)存布局示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • OpenCV邊緣提取算法流程的實(shí)現(xiàn)(附DEMO)

    OpenCV邊緣提取算法流程的實(shí)現(xiàn)(附DEMO)

    本文主要介紹了OpenCV邊緣提取算法流程的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • C/C++中extern函數(shù)使用詳解

    C/C++中extern函數(shù)使用詳解

    extern可以置于變量或者函數(shù)前,以標(biāo)示變量或者函數(shù)的定義在別的文件中,提示編譯器遇到此變量和函數(shù)時(shí)在其他模塊中尋找其定義。此外extern也可用來進(jìn)行鏈接指定
    2022-09-09
  • C++基于特征向量的KNN分類算法

    C++基于特征向量的KNN分類算法

    這篇文章主要為大家詳細(xì)介紹了C++基于特征向量的KNN分類算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • C語言數(shù)據(jù)存儲(chǔ)歸類介紹

    C語言數(shù)據(jù)存儲(chǔ)歸類介紹

    使用編程語言進(jìn)行編程時(shí),需要用到各種變量來存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類型,來分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么
    2022-08-08
  • C語言線性表順序存儲(chǔ)結(jié)構(gòu)實(shí)例詳解

    C語言線性表順序存儲(chǔ)結(jié)構(gòu)實(shí)例詳解

    這篇文章主要介紹了C語言線性表順序存儲(chǔ)結(jié)構(gòu)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • 詳解C語言中結(jié)構(gòu)體的使用

    詳解C語言中結(jié)構(gòu)體的使用

    結(jié)構(gòu)體是一些值的集合,這些值稱為成員變量,結(jié)構(gòu)體的每個(gè)成員可以是不同類型的變量。本文將通過示例為大家詳細(xì)講講C語言中結(jié)構(gòu)體的使用,需要的可以參考一下
    2022-07-07
  • C++11 線程同步接口std::condition_variable和std::future的簡單使用示例詳解

    C++11 線程同步接口std::condition_variable和std::future的簡單使用示例詳

    本文介紹了std::condition_variable和std::future在C++中的應(yīng)用,用于線程間的同步和異步執(zhí)行,通過示例代碼,展示了如何使用std::condition_variable的wait和notify接口進(jìn)行線程間同步
    2024-09-09
  • 詳解VS2019 dumpbin查看DLL的導(dǎo)出函數(shù)

    詳解VS2019 dumpbin查看DLL的導(dǎo)出函數(shù)

    這篇文章主要介紹了詳解VS2019 dumpbin查看DLL的導(dǎo)出函數(shù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • C語言編程中分配內(nèi)存空間的相關(guān)函數(shù)

    C語言編程中分配內(nèi)存空間的相關(guān)函數(shù)

    這篇文章主要介紹了C語言編程中分配內(nèi)存空間的相關(guān)函數(shù),分別是malloc()函數(shù)和calloc()函數(shù),需要的朋友可以參考下
    2015-08-08

最新評(píng)論

观塘区| 芷江| 祥云县| 灵璧县| 南澳县| 板桥市| 林口县| 阜新市| 融水| 白河县| 扎兰屯市| 通榆县| 漳平市| 临西县| 武威市| 白水县| 商都县| 康马县| 萍乡市| 威宁| 封开县| 集安市| 通江县| 怀宁县| 高台县| 肇源县| 深水埗区| 广昌县| 元朗区| 光泽县| 麻栗坡县| 全椒县| 会东县| 客服| 龙岩市| 施秉县| 满城县| 绥棱县| 唐河县| 海口市| 青海省|