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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

木块砌墙---解题报告

發布時間:2024/1/1 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 木块砌墙---解题报告 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目詳情

用 1×1×1, 1× 2×1以及2×1×1的三種木塊,


搭建K × 2^N × 1的墻,不能翻轉、旋轉(0<=N<=1024,1<=K<=5)





有多少種方案,輸出結果對1000000007取模。


舉例:

舉個例子如給定N=1 K=2

答案是7,如下圖所示




答題說明 main函數可以不實現,完成給定的子函數calculate即可(之所以給出main,在于方便你在線編譯測試) ================================================================================================================================== 首先,我們把墻倒過來放,即K在下邊,這樣得到的結果會和原來的墻一模一樣,原因很明顯就不證了,倒過來是為了降低時間復雜度。 思路: 每一層有一個狀態值,該值起決于下一層有那幾個位置放了2*1*1的木塊。 比如一層有5個位置(倒過來后,K在下邊,K最大為5)? 第x-1層 只有第1,3位置放了 2*1*1的木塊,那么第x層的狀態就可以表示為10100既20、顯然每層可能的狀態值就是0到2^k-1 一旦某一層的狀態值確定了(也就是該層有那幾個位置被下一層占了),就可以根據這個狀態值,搜出所有該狀態值下的放木塊的方法,而每一種方法,又確定了上一層的狀態值。 由此: 我們設 F(x, y)? 為從上往下x行, 且x行的狀態值為y的總的擺放方案?? 比如F(2,1)?? 表示從上往下數2行(既包含第1行和第2行),且第2行的第一個位置(10000)被第3行占了的情況了 可以擺放的方案數。 狀態轉移式: F(x, y) =? F(x-1, h(1)) + F(x-1, h(2)) + F(x-1, h(3)) + ......+F(x-1,h(g(y))); 其中g(y) 表示一行中,狀態值是y時,該行所有擺放的方案數 每個h都是表示一種該層的擺放方式所確定的上一層的值。比如改行在第1,3位置擺了2*1*1,其他都擺放了1*1*1,那么上一層的狀態值就是20 答案就是F(2*n, 0); 特殊情況: 當最頂上一層的狀態值為2^k-1時,該層的擺放方案是0。 在最頂上一層的上邊有個虛擬層,該層所有狀態值下的F都為1.(便于計算的) 代碼: [cpp] view plaincopyprint?
  • #include?<cstdio> ??
  • #include?<string> ??
  • #include?<cstring> ??
  • ??
  • using?namespace?std;??
  • ??
  • #ifdef?WIN32 ??
  • #define?ll?__int64? ??
  • #else ??
  • #define?ll?long?long ??
  • #endif ??
  • ??
  • ??
  • int?stan?=?0,stak=?0;??
  • ll?f[3000][1<<6];??
  • ??
  • //將二進制轉成十進制 ??
  • ll?bit2int(int?bit[],?int?k)??
  • {??
  • ??
  • ????ll?i=1;??
  • ????ll?ans?=?bit[0];??
  • ????for?(i?=?1;?i?<?k?;i++)??
  • ????????ans?+=?bit[i]?*?(1<<i);??
  • ????return?ans;??
  • }??
  • ??
  • ??
  • ??
  • //十進制轉成2進制 ??
  • void?int2bit(int?bit[],?ll?num)??
  • {??
  • ????memset(bit,0,sizeof(bit));??
  • ????ll?i;??
  • ????for?(i?=?0;?num?!=?0?;?i++)??
  • ????{??
  • ??
  • ????????bit[i]?=?num?%?2;??
  • ????????num/=2;??
  • ????}??
  • }??
  • ??
  • ??
  • ll?all?=?0;??
  • //計算從上往下到第x行(包含上邊所有行)?以x狀態為y?時?的每種一種放法特例所得到的f(x-1,h),加到all上去??
  • void?count(ll?x,int?bit[],ll?n,int?bit2[]);??
  • ??
  • ??
  • //計算從上往下到第x行(包含上邊所有行)?以x狀態為y?時的方法總數 ??
  • int?dp(ll?x,ll?y)??
  • {??
  • ????if?(x?==?1?&&?y?==?(1<<stak?)-1)?return?0;??
  • ????if?(x?==?0)?return?1;??
  • ????if?(f[x][y]?!=?0)?return?f[x][y];//已經計算過了??
  • ????all?=?0;??
  • ??
  • ??
  • ????//第x行的2進制表示 ??
  • ????int?bit[6];??
  • ????int2bit(bit,y);??
  • ??
  • ??
  • ????//第x-1行的2進制表示 ??
  • ????int?bit2[6];??
  • ????memset(bit2,0,sizeof(bit2));??
  • ??
  • ????//計算 ??
  • ????count(x,bit,0,bit2);??
  • ????return?(f[x][y]?=?all);??
  • }??
  • ??
  • //第x行,從第0到n位的都放過了 ??
  • void?count(ll?x,int?bit[],ll?n,int?bit2[])??
  • {??
  • ????//遞歸邊界 ??
  • ????if?(n>=stak)??
  • ????{??
  • ????????//將得到的bit2[]轉成狀態h,就可以得到f(x-1,h).?加到?all上面去 ??
  • ????????all?=?(all?+?dp(x-1,bit2int(bit2,stak)))??%?1000000007?;??
  • ????????return?;??
  • ????}??
  • ????//這位被占了,那么這位不能放東西,且x-1的這位,必然是0 ??
  • ????if?(bit[n]?==?1)??
  • ????{??
  • ????????bit2[n]=0;??
  • ????????count(x,bit,n+1,bit2);??
  • ????}??
  • ????//如果這位是空的,那么3種方塊都有可能放 ??
  • ????else??
  • ????{??
  • ????????//放1*1*1 ??
  • ?????????bit2[n]?=?0;??
  • ?????????count(x,bit,n+1,bit2);??
  • ?????????//放2*1*1 ??
  • ?????????bit2[n]?=?1;??
  • ?????????count(x,bit,n+1,bit2);??
  • ?????????//放1*2*2?條件是這一位置不是最后一位,且下一位置可以放 ??
  • ?????????if?(n<stak?&&?bit[n+1]?==?0?)??
  • ?????????{??
  • ??
  • ?????????????bit2[n]?=?0;??
  • ?????????????bit2[n+1]?=?0;??
  • ?????????????count(x,bit,n+2,bit2);??
  • ?????????}??
  • ??
  • ????}??
  • ??
  • ??
  • }??
  • ??
  • int?calculate(int?n,int?k)???
  • {??
  • ????stak?=?k;??
  • ????stan?=?n;??
  • ????memset(f,0,sizeof(f));??
  • ????return?dp(2*n,0);??
  • }??
  • ??
  • ??
  • //start?提示:自動閱卷起始唯一標識,請勿刪除或增加。? ??
  • int?main()?{??
  • ????//自行定義n,k ??
  • ??
  • ???int?n,k;??
  • ???//為了調試,實際提交要去掉這行 ??
  • ???while(1)??
  • ???{??
  • ???????scanf("%d%d",&n,?&k);??
  • ???????printf("%d\n",calculate(n,k));??
  • ???}??
  • ????
  • ????return?0;??
  • }??
  • //end?//提示:自動閱卷結束唯一標識,請勿刪除或增加。??
  • 結束語: 這題有種直覺,可以更簡單。。沒多考慮,直接這么寫了。。。有更好方法的朋友,留個言!

    總結

    以上是生活随笔為你收集整理的木块砌墙---解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。

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