日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一、约瑟夫问题

發布時間:2025/3/21 编程问答 11 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一、约瑟夫问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、約瑟夫問題

文章目錄

  • 一、約瑟夫問題
    • 題目描述
    • 解題思路
    • 上機代碼:
      • 解法一:數組模擬
      • 解法二:鏈表模擬

題目描述

約瑟夫問題是一個經典的問題(大一我們講過)。這個問題可以用數組,也可以用鏈表。作為復習,大家可以試試你自己的算法。

已知n個人(不妨分別以編號1,2,3,…,n 代表 )圍坐在一張圓桌周圍,從編號為 k 的人開始,從1開始順時針報數1, 2, 3, …,順時針數到m 的那個人,出列并輸出。然后從出列的下一個人開始,從1開始繼續順時針報數,數到m的那個人,出列并輸出,…依此重復下去,直到圓桌周圍的人全部出列。

  • 輸入:n, k, m
  • 輸出:按照出列的順序依次輸出出列人的編號,編號中間相隔一個空格,每10個編號為一行。

非法輸入的對應輸出如下

a)
輸入:n、k、m任一個小于1
輸出:n,m,k must bigger than 0.

b)
輸入:k>n
輸出:k should not bigger than n.

測試輸入期待的輸出時間限制內存限制額外進程
測試用例 19,3,24 6 8 1 3 7 2 9 51秒64M0
測試用例 210,12,3k should not bigger than n.1秒64M0

解題思路

這是一個典型的模擬題,我們可以用兩種方式來實現:數組或者鏈表。

  • 采用數組的方式,初始化一個元素值都為0的數組,每次選中出局元素后將其值置為-1,以后遇到-1則跳過,非-1則計數。直到所有元素全部出局,即數組可用長度為0時終止

  • 采用鏈表的方式,初始化一個長度為n的循壞鏈表,每次選中出局結點后將其刪除,將余下結點連接,繼續計數。直到所有結點均被刪除為止

上機代碼:

解法一:數組模擬

#include <stdio.h> #include <stdlib.h> #include <string.h> #define LineFeed 10 /*解法一,數組模擬 */ int main() {/*n,k,m分別對應n個人,從編號k開始,每次數m個*/int n=0, k=0, m=0;scanf("%d,%d,%d", &n, &k, &m);/*非法輸入的對應輸出*/if(n<1 || k<1 || m<1){printf("k should not bigger than n.");return 0;}if (k>n){printf("k should not bigger than n.");return 0;}/*正常輸入,用數組模擬約瑟夫環*///初始化int a[10010];memset(a,0,sizeof(a));//數組長度,換行標志,位移記錄int len=n, flag=0, ans=k;while(len){//位移指針,計數器int i=ans-1, count=0;while(i++){//保證指針循環索引if(i>n){i=i%n;}//-1即已經出局,跳過if (a[i]==-1){continue;}count++;if(count==m)//到達m步{a[i]=-1;len--;flag++;ans=i+1;//記錄當前位移if(flag==LineFeed)//累計輸出10個元素,換行{printf("%d\n", i);flag=0;}else if(len>0){printf("%d ", i);}else//最后一個元素換行{printf("%d\n", i);}break;}}}return 0; }

解法二:鏈表模擬

#include <stdio.h> #include <stdlib.h> #define LineFeed 10 /*解法二,鏈表模擬 */ typedef struct node {int data;struct node *next; }NODE, *PNODE;int main() {/*n,k,m分別對應n個人,從編號k開始,每次數m個*/int n=0, k=0, m=0;int flag=0;//換行標志scanf("%d,%d,%d", &n, &k, &m);/*非法輸入的對應輸出*/if(n<1 || k<1 || m<1){printf("k should not bigger than n.");return 0;}if (k>n){printf("k should not bigger than n.");return 0;}/*正常輸入,用循環鏈表模擬約瑟夫環*///初始化頭結點PNODE head,p,q;head=(PNODE)malloc(sizeof(NODE));head->data=-1;head->next=head;//頭插法建立鏈表for (int i = n; i > 0; i--){p=(PNODE)malloc(sizeof(NODE));p->data=i;p->next=head->next;head->next=p;}//構建循環while(p->next!=head){p=p->next;}p->next=head->next;free(head);//找到計數的初始位置的前一個結點for (int i = 0; i < k-1; i++){p=p->next;}//開始循環剔除結點for (int i = 1; i <= n; i++){//走m-1步,下一個就是要剔除的結點for (int j = 0; j < m-1; j++){p=p->next;}//鎖定要剔除的結點q=p->next;//調整輸出flag++;if(flag==LineFeed)//累計輸出10個元素,換行{printf("%d\n", q->data);flag=0;}else if(i==n)//最后一個結點,換行{printf("%d\n", q->data);}else{printf("%d ", q->data);}//剔除該結點p->next=q->next;free(q);}return 0; }

總結

以上是生活随笔為你收集整理的一、约瑟夫问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。