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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

杭电 汉诺塔问题总结

發(fā)布時間:2025/4/16 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 杭电 汉诺塔问题总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

看了一下杭電的各種漢諾塔問題,遇到些奇奇葩葩的小問題,也有很多很好的思想,比如最后一題,來來回回的顛倒很有意思??偨Y(jié)一下;

Pro.ID 1207 :http://acm.hdu.edu.cn/showproblem.php?pid=1207

意思是給把原始的漢諾塔問題中的3根柱子改為4根。做了半天各種WA。查了一下,有一篇文章詳細講了一下,還做出了遞歸公式以及數(shù)學(xué)公式:

地址如下:http://www.cnblogs.com/fanzhidongyzby/archive/2012/07/28/2613173.html.

代碼如下:

?

#include<cstdio> #include<cmath> #include<algorithm> //F(n)=min(2*F(n-r)+2^r-1),(1≤r≤n) using namespace std; int main() {int n,m;long long Min,f[65];f[1]=1;f[2]=3;for(int i=3;i<=65;i++){Min=99999999;for(int j=1;j<i;j++)Min=min(2*f[j]+pow(2.0,i-j)-1,Min*1.0);f[i]=Min;}while(~scanf("%d",&n))printf("%lld\n",f[n]);return 0; }


按照公式寫就是了,寫的時候需要注意一下精度問題。2^r可以寫為1<<r,不過因為數(shù)字常數(shù)1默認是32位,所以如果要使用位移的話,一定要先聲明一個longlong類型的變量來進行位移,否則 就會出現(xiàn)溢出錯誤,這個我糾結(jié)了一陣子,感覺沒錯,一提交就WA,然后試了試64發(fā)現(xiàn)果然是負數(shù)。

?

哎,基礎(chǔ)還是不扎實啊。

用pow函數(shù)因為返回的是一個double類型,min函數(shù)里比較也是用double來做的,只是在最后賦值的時候取int型就可以,所以不會出錯。


Pro.ID ?1995?漢諾塔V

http://acm.hdu.edu.cn/showproblem.php?pid=1995

這個是普通的漢諾塔,最優(yōu)的步數(shù)是2^n-1,只不過問的第i個盤子移動的次數(shù)。依然是用遞歸,在紙上畫畫就能出來。

注意了,第i盤子,不用考慮底下的盤子,只用看之上的經(jīng)過一個柱子到達目的地。即F[n]=2*f[n-1]

代碼:

?

#include<iostream>using namespace std;int main() {__int64 s[61] = {0, 1};int n, i, t, m;for(i = 2; i < 61; i++)s[i] = s[i - 1] * 2;cin >> t;while(t--){cin >> n >> m;cout << s[n - m + 1] << endl;} }

Pro.ID?漢諾塔VI

?

http://acm.hdu.edu.cn/showproblem.php?pid=1996

是問所有步驟,注意不是最優(yōu)的,是全部(當(dāng)然不包括錯誤的步驟)

每一個盤子可以放到3根柱子的任意一個,所以是3^n。比如正確的是直接從a->c,現(xiàn)在可以a->b然后在b->c,就是多了2種。每一個都多了2種,所以是3^n。

代碼:

?

#include<iostream> #include<math.h> #include<stdio.h> using namespace std; int main() {__int64 t,n,i;__int64 sum,a[100]={3,};while(cin>>t)while(t--){cin>>n;for(i=1;i<n;i++)a[i]=a[i-1]*3;cout<<a[n-1]<<endl;}return 0; }

Pro.ID 1997?漢諾塔VII

?

http://acm.hdu.edu.cn/showproblem.php?pid=1997

題目是說,給定某一時刻的三個柱子上的盤子,問這個是不是符合最優(yōu)解過程中某一時刻的狀態(tài)。

思想是:

對一個含有n個盤子,從A柱移動到C柱借助B柱的漢諾塔,第n個盤子移動到C柱過程是這樣子的:首先將其余的n-1個盤子移動到B柱,然后第n個盤子直接移動到C柱。在這過程中,第n個盤子只出現(xiàn)在A柱和C柱兩個柱子上,也即第n個盤子不可能出現(xiàn)在B柱上。因此對于當(dāng)前移動的盤子,只需檢查其所在的柱子是否符合這個要求,如果出現(xiàn)在B柱上,則顯然進入了錯誤移動中。這是本題求解思想精髓所在。

具體的內(nèi)容請參考這篇博客:http://blog.csdn.net/z690933166/article/details/8605261

代碼就不貼了,上邊這個博客里寫的很詳細。

Pro.ID 2064?漢諾塔III

http://acm.hdu.edu.cn/showproblem.php?pid=2064

還是遞推:num[i]=3*num[i-1]+2;

不解釋了,代碼如下:

?

#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; unsigned long long num[36]; int main() { num[1]=2;num[2]=8;for(int i=3;i<=35;i++)num[i]=3*num[i-1]+2;int n;while(~scanf("%d",&n))cout<<num[n]<<endl;return 0; }


Pro.ID 2077?漢諾塔IV(參考了 zz_zigzag的博客)

?

http://acm.hdu.edu.cn/showproblem.php?pid=2077

好無聊啊,把上邊的規(guī)則給改了,只是最大的可以放上邊。其實感覺這個題目跟之前那個1027題目有點想通之處,在1027中說的是4根柱子,所以通用的這3個步驟其實并非最優(yōu)解:

?

(1)???????1柱借助3…M柱子將n-(M-2)個盤子移動到2柱上。

(2)???????M-2個通過3…M-1柱簡單的移動到M柱上【2*(M-2)-1步驟】。

(3)???????2柱借助13…M-1柱子將n-(M-2)個盤子移動到M柱上。

如果有n個盤子,則需要前n-1個挪到中間的盤子上,然后最大的盤子挪到最右面,需要兩步,把前(n-1)個盤子從左邊挪到中間是和從中間挪到右邊需要相同的次數(shù)。而a數(shù)組中存放的就是那個前n-1個盤子挪動到相同位置需要的次數(shù)。結(jié)果即為a[i-1]*2+2。

所以我直接想成了是f[n]=2*f[n-1]+2,結(jié)果錯了。【因為是需要n-1個盤子前進一步】


而求a數(shù)組需要用到遞推。公式為第i個為前n-1個移動次數(shù)的三倍加一,簡化到兩個盤子,小的先移動兩次到最右邊,大的移到中間,然后小的在移回中間,小的移動了三次,而大的移動了一次,就使他們?nèi)颗矂恿艘粋€位置

所以代碼如下:

?

#include<stdio.h> int a[20]={0,1};int main() {int i,T;for(i=2;i<21;i++){a[i]=3*a[i-1]+1; }scanf("%d",&T);while(T--){scanf("%d",&i);printf("%d\n",2*a[i-1]+2);}return 0; }


Pro.ID 2175?漢諾塔IX

?

http://acm.hdu.edu.cn/showproblem.php?pid=2175

普通漢諾塔,問在最優(yōu)步驟中的第i步是哪一個盤子,跟1995那個題目剛好相反。不過這個有點像數(shù)論題。

這樣想,假設(shè)是4個盤子,考慮第三個,在第4步的時候?qū)?盤從A移動到C【設(shè)目的地是B】,此時1,2盤在B上,設(shè)時間為T,然后將1,2盤移動到C上,(需要3步)再把4盤移動到B上,此時的格局為4盤在B上,1,2,3,在C上,距T過去了1+3=4步,那么3號盤什么時候再動呢?把1,2移走,3就可以放到B上了,移走1,2需要花費3個步驟,因此距T4+3+1也就是第8步,總體是第12步時,3號盤子會再次移動?,F(xiàn)在看明白了吧,就是基數(shù)倍的2^(i-1)時,i號盤子會移動。

代碼如下:

?

#include<iostream> using namespace std; int main() {__int64 a[65];a[1]=1;__int64 i,n,r;__int64 m;for(i=2;i<=63;i++)a[i]=2*a[i-1];while(~scanf("%I64d%I64d",&n,&m),n+m){for(i=1;i<=n;i++){r=m/a[i];if(r%2==1&&m%a[i]==0)printf("%I64d\n",i);}}return 0; }

?


Pro.ID 2184?漢諾塔VIII

感覺這個題目非常的好,挺有意思的,問普通漢諾塔,N個盤子,在最優(yōu)解的第M步時,每個柱子上的盤子的狀態(tài)。

想了半天,也沒什么思路,但有一點是絕對可以確定的,就是一般解簡單漢諾塔過程的問題都是使用遞歸,可以得到全部過程,但是當(dāng)N稍微到10以上的時候必然遞歸很慢,所以直接遞歸模擬必然是錯誤的,但是根據(jù)上一題目,第i個步移動哪一個盤子中確定的,第K個盤子在 ?奇數(shù)*2^(K-1)時移動可以得到些思想,必然是根據(jù)步數(shù)來確定盤子。

但是想了老半天也不太清楚那個遞歸改怎么寫,好像每一次判斷都要做除法到是可以確定某一個盤子,但是如何確定所有的盤子呢?糾結(jié)啊

查了半天,找到了一個大神的代碼。

地址在:http://blog.lchx.me/index.php/hdu-2184-%E6%B1%89%E8%AF%BA%E5%A1%94viii/

講的非常的詳細,我把思路以及代碼粘過來大家分享一下:

/*定義數(shù)組a,其中a[i]表示完成一次i層漢諾塔移動的次數(shù)。 指針o,p,q分別表示三個位置。 起始狀態(tài)為n層都在o上,要往q方向移動。 然后分成兩種情況: 1、 m<=a[n-1]; 此時,第n層沒機會移動,那么就相當(dāng)于o上的n-1層往p上移動。 使其狀態(tài)和起始狀態(tài)一致,我們要交換p和q。 2、 m>a[n-1]; 此時,先進行到下面狀態(tài),上面n-1層移動到p位置,第n層移動到q位置,消耗了a[n-1]+1次移動。 接下來就變成p上的n-1層往q上移動,只要交換o,p,令m=m-a[n-1]-1即可。通過上述操作,都可以得到第n層的位置,并且問題變成n-1層都在o上,要往q方向移動。 */ #include<cstdio> #include<algorithm> #include<iostream> using namespace std; int main() {unsigned __int64 m,a[64];int row[3][66];a[1]=1;a[0]=0;for(int i=2;i<=63;i++)a[i]=a[i-1]*2+1;int t;scanf("%d",&t);while(t--){int n;scanf("%d %I64u",&n,&m);int *start,*mid,*end;start=row[0];mid=row[1];end=row[2];*start=*mid=*end=1;while(n){n--;if(m<=a[n]){*(start+*start)=n+1;//從第二個位置開始記錄盤子(*start)++;//第一個位置表示的是這個柱子一共有多少個盤子swap(end,mid);}else{*(end+*end)=n+1;(*end)++;swap(start,mid);m-=(a[n]+1);} }for(int i=0;i<3;i++){printf("%d",row[i][0]-1);for(int j=1;j<row[i][0];j++)printf(" %d",row[i][j]);printf("\n");}}return 0; }


?


Pro.ID?漢諾塔 X

http://acm.hdu.edu.cn/showproblem.php?pid=2511

進一步加強條件,在求第m步時是哪個盤子動,怎么動。

必然遞歸啊。把上上個題目修改就可以了。具體的就不多說了,在注釋里有詳細解釋

?

#include<iostream> using namespace std;__int64 a[65]; void solve(int n,__int64 m,int start,int end) {int third=6-start-end;//得到第3跟柱子__int64 mid=a[n];if(m==mid) //如果是當(dāng)前盤子移動,直接從start-->end{printf("%d %d %d\n",n,start,end);return ;}if(m<mid)//當(dāng)前盤子無法移動,必然是上邊的某個盤子動,并且移動一定是到third號柱子上,遞歸求解solve(n-1,m,start,third);else//需要先移動當(dāng)期盤子下部的盤子(參考2184題目)solve(n-1,m-mid,third,end); }int main() {__int64 m;a[1]=1;int n;for(int i=2;i<=63;i++)a[i]=2*a[i-1];int t;while(~scanf("%d",&t)){while(t--){scanf("%d%I64d",&n,&m);solve(n,m,1,3);}}return 0; }

?

最后一個Pro.ID ?2587:很O_O的漢諾塔

http://acm.hdu.edu.cn/showproblem.php?pid=2587

真心是跪了,

感謝hr_whisper的詳細講解,這里已經(jīng)寫的很清楚了:http://blog.csdn.net/murmured/article/details/9943947

?

?

總結(jié)

以上是生活随笔為你收集整理的杭电 汉诺塔问题总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 男女一区| 成人网页在线观看 | 一区免费在线 | 亚洲图区欧美 | 特色特色大片在线 | 在线观看免费视频国产 | 丁香婷婷一区二区三区 | 神马伦理视频 | 久久图库 | 翔田千里一区二区三区av | av综合一区 | 国产精品久久久久久久久久久不卡 | 日本一级淫片免费放 | 91麻豆精品国产理伦片在线观看 | 日本三级中国三级99人妇网站 | 日韩在线不卡视频 | 99久久久国产精品无码性 | 国产精品视频a | 91久久精品美女高潮 | 国产在线欧美在线 | 九九热最新 | 三级伦理视频 | 国产在线极品 | 国产午夜手机精彩视频 | 欧美另类视频在线观看 | 永久在线免费观看 | 久久久久久久麻豆 | 欧美国产成人精品一区二区三区 | 91看视频 | 欧美伦理片网站 | 综合网中文字幕 | 精品亚洲aⅴ无码一区二区三区 | 瑟瑟视频免费观看 | 欧美日韩激情视频在线观看 | 鲁丝片一区二区三区 | 欧美日韩亚洲在线观看 | 欧美大片一区二区 | 啪啪av| 日本三级中国三级99人妇网站 | 亚洲成人av中文字幕 | 青青草日韩 | 成人网av| 亚洲激情影院 | 亚洲精品高清视频 | 亚洲国产123 | 亚洲成人福利在线 | 看全色黄大色黄大片女一次牛 | 久射久| 不良视频在线观看 | 国产在线视频第一页 | 久久人人爽人人爽人人片亚洲 | 国产精品偷乱一区二区三区 | 青青草网址| 亚洲中文字幕在线一区 | 伦理片一区二区 | 欧美熟妇7777一区二区 | 亚洲黄色免费视频 | 美女毛片在线 | 久久国产乱子 | 97精品人妻一区二区三区蜜桃 | 久久免费视频99 | 黄色一集片| 久久亚洲网站 | 欧美日韩在线中文字幕 | 男女午夜视频 | 日韩人妻无码精品久久免费 | a级片在线视频 | 91欧美大片 | 黄色网战在线观看 | 亚洲在线网站 | 欧美综合网站 | 天天做天天射 | 一区二区久久精品66国产精品 | 久久亚洲AV无码 | 国产一区二区视频免费观看 | 公车乳尖揉捏酥软呻吟 | 国产人妻人伦精品1国产丝袜 | 国产精品久久久久久亚洲影视 | 欧美在线免费观看 | 古装三级吃奶做爰 | h视频在线免费看 | 久久精品无码一区二区三区毛片 | 草草影院一区二区三区 | 狠狠干婷婷 | 国产乱淫a∨片免费观看 | 少妇中出视频 | 国产人成在线观看 | 超碰在线综合 | 成年人免费黄色 | 在线午夜 | 国产无遮挡一区二区三区毛片日本 | 悠悠色在线 | 一区二区麻豆 | 欧美激精品 | 色婷婷av一区二区三区四区 | 奇米精品一区二区三区四区 | 欧美日韩乱 | 成人午夜在线观看 | 91欧美激情一区二区三区成人 |