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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

映射递归循环-约瑟夫环问题递归解法的一点理解

發布時間:2025/3/13 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 映射递归循环-约瑟夫环问题递归解法的一点理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

先說明一點,如果有什么不對的地方,歡迎大家批評指正。

先來看這個類型的某個題目描述:

約瑟夫生者死者游戲

約瑟夫游戲的大意:30個游客同乘一條船,因為嚴重超載, 加上風浪大作,危險萬分。因此船長告訴乘客,只有將全船 一半的旅客投入海中,其余人才能幸免于難。無奈,大家只 得同意這種辦法,并議定30 個人圍成一圈,由第一個人數起,依次報數,數到第9人,便把他投入大海中,然后再從 他的下一個人數起,數到第9人,再將他投入大海中,如此 循環地進行,直到剩下 15 個游客為止。問:哪些位置是將 被扔下大海的位置?

不失一般性,將 30 改為一個任意輸入的正整數 n,而報數 上限(原為9)也為一個任選的正整數k

第一次看到這個題目,我首先想到的是用 鏈表 或者是 數組 來模擬,但是當我寫完之后,與大神對答案,發現他的c語言代碼是這么寫的:

int ysfdg ( int sum, intvalue, intn)
{
if ( n == 1 )
return ( sum + value - 1 ) %sum;
else
return ( ysfdg ( sum-1, value,n-1 ) +value ) %sum;
}

7行。。。。。。再見(已經不能做朋友了嗎。。。)

sum指的是總人數,value指的是每次最大報到的數值,n是第n次,該函數每次可以求出第n次扔海里的人的編號,( ysfdg指的是約瑟夫遞歸 ) 。

大神飄然而去,而我懵逼了一天,才明白了這段代碼的意思。

舉個栗子:

總人數sum為10人,從0開始,每報到4就把一人扔下去(value=4)。

初始情況為:

0 1 2 3 4 5 6 7 8 9

扔下去一個之后:

0 1 2 4 5 6 7 8 9

此時,這些編號已經不能組成一個環,但是可以看出4至2之間還是連著的(4 5 6 7 8 9 0 1 2),且下一次報數將從4開始。但是,之后的報數將總要考慮原編號3處的空位問題。

如何才能避免已經產生的空位對報數所造成的影響呢?

可以將剩下的9個連續的數組成一個新的環(將2、4連接),這樣報數的時候就不用在意3的空位了。但是新產生的環的數字并非連續的,報數時不像之前那樣好處理了(之前沒人被扔海里時下一個報數的人的編號可以遞推,即(當前編號+1)%sum ),無法不借助存儲結構得知下一個應該報數的現存人員編號。

如何使新環上的編號能夠遞推來簡化我們之后的處理呢?

可以建立一種有確定規則的映射,要求映射之后的數字可以遞推,且可以將在新環中繼續按原規則報數得到的結果逆推出在舊環中的對應數字。

方法:將它與 sum-1 個人組成的(0 ~ sum-1)環一 一映射。

比如之前的栗子,將剩余的 9 人與 9 人環(0~8)一 一映射。既然 3 被扔到海里之后,報數要從4開始 (4 其實在數值上等于最大報數值),那么就將4映射到0~8的新環中0的位置,也就是說在新環中從0開始報數即可,且新環中沒有與3對應的數字,因此不必擔心有空位的問題。從舊環的 4 開始報數等效于從新環中的 0 開始報數。

原始 0 1 2 3 4 5 6 7 8 9

舊環 0 1 2 4 5 6 7 8 9

新環 6 7 8 0 1 2 3 4 5

新環有這么一個優勢: 相比于舊環中2與4之間在數學運算上的不連續性,新環8和0之間在對9取余的運算中是連續的,也就是說根本不需要單獨費心設計用以記錄并避開已產生的空位(如 編號3)的機制 ,新環的運算不受之前遺留結果的掣肘。同時只要能將新環與舊環的映射關系逆推出來,就能利用在新環中報數的結果退出之前舊環中的報數結果。

以下是新環與舊環中下一個要人扔海里的人位置:

舊環 0 1 2 4 5 6 7 8 9

^

新環 6 7 8 0 1 2 3 4 5

^

如何由新環中的 3 得到舊環中的 7 呢。其實可以簡單地逆推回去 : 新環是由 (舊環中編號-最大報數值)%舊總人數 得到的,所以逆推時可以由 ( 新環中的數字 + 最大報數值 )% 舊總人數 取得。即 old_number = ( new_number + value ) % old_sum.

如 : ( 3 + 4 ) % 10 =7 .

也就是說在,原序列( sum ) 中第二次被扔入海中編號可以由新序列( sum - 1) 第一次扔海里的編號通過特定的逆推運算得出。

而新序列 (sum -1)也是(從0開始)連續的,它的第二次被扔入海中的編號由可以由(sum - 2)的第一次扔入海里的編號通過特定的逆推運算得出,并且它的第二次被扔入海中的編號又與原序列中的第三次被扔入海里的編號是有對應關系的。

也求是說有以下推出關系:

(sum-2)環的第1次出環編號 >>>(sum-1)環的第2次出環編號 >>>(sum)環的第3次出環編號

即 在以 k 為出環報數值的約瑟夫環中, m人環中的第n次出環編號可以由 (m-1) 人環中的第 (n-1) 次出環編號通過特定運算推出。

幸運的是,第一次出環的編號是可以直接求出的,也就是說,對于任意次出環的編號,我們可以將之一直降到第一次出環的編號問題,再一 一 遞推而出。

注意 以下圖示中的環數字排列都是順序的,且從編號0開始。

由圖知,10人環中最后入海的是4號,現由其在1人環中的對應編號0來求解。

通過以上運算,其實我們已經求出分別位于9個環中九個特定次數的結果,只不過我們需要的是10人環的結果罷了。

這種方法既可以寫成遞歸也可以寫成循環,它對于求特定次數的出環編號效率較高。

遞歸就比較好寫了,出口即是當次數為1時。

實際編號是從1開始,而不是0,輸出時要注意轉換。

借此就可以看懂那個大神的代碼了。

以下是三種約瑟夫環解法(數組,鏈表,遞歸)的c語言代碼,作者水平不高,將就看看吧 ╮(╯_╰)╭:

#include<stdio.h> #include<stdlib.h> #define FAIL 0 #define SUCCESS 1typedef struct gamenode {int number;struct gamenode* next;} node;//讀入初值 int getvalue(int* sum,int* count,int* alive) {printf("請輸入要參與約瑟夫生存游戲的人數:(人數>0)\n");while(1){scanf("%d",sum);if(*sum>0)break;printf("輸入無效,請重新輸入。\n");};printf("請輸入能報到的最大數字:(1<=數字)\n");while(1){scanf("%d",count);if(*count>=1)break;printf("輸入無效,請重新輸入。\n");};printf("請輸入要求最后存活的人數:(0<=人數<=%d)\n",*sum);while(1){scanf("%d",alive);if(*alive>=0&&*alive<=*sum)break;printf("輸入無效,請重新輸入。\n");};return SUCCESS; }//數組解法 int ysfsz(int n,int k,int s) {int i=0,*p=NULL,sum=n-k,j=1,o=0,pr=0;if ((p=(int*)malloc(sizeof(int)*n))==NULL){printf("FAIL!\n");return FAIL;}for(i=0;i<n;i++){p[i]=1;}i=0;while(1){if (sum==0)break;if (j==s&&p[i]==1){ p[i]=0;j=1;--sum;}else if(p[i]==1){ j++;}i++;i=i%n; }printf("\n生存下來的人的位置是:");for(i=0;i<n;i++){if(p[i]==1)printf("%d ",i+1);}printf("\n");printf("\n扔海里的位置是:");for(i=0;i<n;i++){if(p[i]==0)printf("%d ",i+1);}printf("\n");free(p);return SUCCESS; }//鏈表解法 int ysflb(int n,int k,int s) {node *h=NULL,*p=NULL,*q=NULL;int i=0;if ((h=(node*)malloc(sizeof(node)*n))==NULL){printf("FAIL!\n");return FAIL;}h->number=1;h->next=h;q=h;for(i=1;i<n;i++){if ((p=(node*)malloc(sizeof(node)*n))==NULL){printf("FAIL!\n");exit (-1);}else{ p->next=NULL;p->number=i+1;q->next=p;q=q->next;}}q->next=h;p=h;i=1;k=n-k;while(k>0){if(i==s){if(p!=p->next){q->next=p->next;printf("%d號已被扔進海里。\n",p->number);free(p);p=q->next;}else{printf("%d號已被扔進海里。\n",p->number);p=q=h=NULL;}--k;}else{p=p->next;q=q->next;}++i;if(i>=s+1)i=1;}if(p!=NULL){printf("幸存下來的人有:");h=p;p=p->next;while(p!=h){q=p->next;printf("%d ",p->number);free(p);p=q;}printf("%d ",h->number);free(h);}elseprintf("全部扔海里去了。\n");return SUCCESS; }//遞歸解法 int ysfdg(int sum,int value,int n) {if(n==1)return (sum+value-1)%sum;elsereturn (ysfdg(sum-1,value,n-1)+value)%sum; }//主函數 int main(void) {int sum=0,count=0,alive=0,i=0;//讀入總人數,報數值,存活人數getvalue(&sum,&count,&alive);/*------------------------------------------------------------*/ //1.約瑟夫環的數組解法//ysfsz(sum,alive,count);//2.約瑟夫環的鏈表解法//ysflb(sum,alive,count);//3. 約瑟夫環遞歸解法for(i=1;i<=sum-alive;i++)printf("第%2d個被扔海里人的編號:%2d\n",i,ysfdg(sum,count,i)+1);return 0; }

總結

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

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

主站蜘蛛池模板: 成人在线一区二区 | 国产成人aⅴ | 久久久精品久久久 | 少妇特殊按摩高潮惨叫无码 | 亚洲精品激情视频 | 日本免费一区二区在线 | 一级做a免费 | 区一区二视频 | 极品尤物一区二区三区 | 亚洲裸体网站 | 1024手机看片国产 | 亚洲图片欧美视频 | 日本欧美不卡 | 日韩精品欧美 | 激情一区二区三区 | 亚洲欧美综合另类 | 免费欧美一区 | 成人av在线播放网站 | 波多野结衣一区二区三区高清av | 免费毛片在线播放 | 日b免费视频 | 国产精品久久久久久无人区 | 亚洲天堂欧美在线 | 亚洲依依| 久久高潮视频 | 精品国产成人av | 亚洲精品激情视频 | 黄瓜视频在线免费看 | 午夜一区二区视频 | 亚洲欧美一区二区三区不卡 | 美女免费av | 精精国产xxxx视频在线 | www.99视频| 色av吧 | 大尺度网站在线观看 | 欧美成人午夜免费视在线看片 | 两性午夜视频 | 天天综合网久久 | 国产一区二区视频在线观看 | 人体写真 福利视频 | 精品在线免费视频 | 亚洲国产大片 | 欧美大片在线看 | 日韩视频一区在线观看 | 欧美激情第五页 | www.五月激情| 无码人妻久久一区二区三区不卡 | 欧美三日本三级少妇三级99观看视频 | 精品麻豆av | 久久精品国产亚洲AV高清综合 | 超碰伊人| 日本成人在线免费视频 | 中文字幕一区二区三区四区不卡 | www.四虎com | 处女朱莉第一次 | 亚洲国产中文字幕在线 | 伊人久久免费视频 | 欧美国产黄色 | 日本不卡一区在线观看 | 国产成人精品久久二区二区91 | 午夜视频 | 日本爱爱免费视频 | 96福利视频 | 久久福利影视 | 婷婷九月 | 骚鸭av | 久热只有精品 | 国产精品久久久久久免费 | 久久99国产精品久久99果冻传媒 | 骚av在线| av色资源 | 久久最新视频 | 91午夜免费视频 | 亚洲婷婷在线视频 | 免费黄网在线看 | 精品日本一区二区三区 | 免费男女视频 | 激情综合五月婷婷 | 绯色av一区 | av自拍一区 | 色六月婷婷 | 中文字幕8 | 欧美日韩五月天 | 免费精品视频 | 亚洲午夜久久久久久久久红桃 | 成人毛片在线 | 色综合一区二区三区 | 久久夜色精品亚洲 | 青青操在线 | 亚洲图片欧美激情 | 五月天综合视频 | 女女同性女同一区二区三区按摩 | 日韩一区二区三区高清 | 国产精品va | 69精品一区二区 | 久久无码人妻精品一区二区三区 | 日韩精品色 | 调教丰满的已婚少妇在线观看 | 午夜一二三区 |