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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

HDU 4332 Constructing Chimney [状态压缩+矩阵]

發布時間:2024/4/11 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU 4332 Constructing Chimney [状态压缩+矩阵] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  煙囪是一個3*3的中空構造,給定煙囪的高度,問用1*1*2的磚頭搭成這個煙囪有多少種方法。 

   

  首先用一個8位二進制數表示某一層的狀態。枚舉上下兩層的狀態,判斷這兩個狀態是否可以相鄰,上一層必須將下層填滿,但是上層自身可以有空格。當下層為0時,上層必須為1,表示放一個豎著的矩形塊,因此必須滿足up_stat|low_stat=255,上層中除了豎著的磚頭,都是單個或連續個橫放的磚頭,所以必須滿足up_stat&low_stat中的連續1都是偶數個。注意循環的問題,比如0的位置是1,7位置也是1,而實際上0和7是相鄰著的。

  相鄰層的狀態會構造出一個矩陣表示轉化關系,為0時代表不能相鄰,否則該值表示轉化方法數,注意當low_stat=up_stat=255時,會有兩種情況,其它的狀態都是一種情況。

  因為狀態較多,即使使用矩陣乘法加速,復雜度也是很高的,交上去果然是超時了。仔細一想,第一層的狀態必須是255,中間有很多狀態實際上無用的,比如有奇數個1的狀態,這些狀態根本就是不可達的,于是以255為第一層搜索了一下,果然有用的狀態只有70個。復雜度為70^3*log(10^9),優化一下大概跑1秒左右。

1 #include <string.h> 2 #include <stdio.h> 3 #define MOD 1000000007 4 #define MAXN 71 5 typedef __int64 LL; 6 int cas,n; 7 int dmat[MAXN][MAXN],id[256],ids; 8 struct matrix{ 9 int mz[MAXN][MAXN]; int n,tmp_cal[35]; 10 #define FOR(i) for(int i=1;i<=n;i++) 11 //初始化矩陣,空矩陣,單位矩陣和dmat矩陣 12 void init(int nn,int type){ 13 memset(tmp_cal,0,sizeof tmp_cal);n=nn; 14 if(type==0)FOR(i)FOR(j)mz[i][j]=0; 15 else if(type==1)FOR(i)FOR(j)mz[i][j]=(i==j)?1:0; 16 else FOR(i)FOR(j)mz[i][j]=dmat[i][j]; 17 } 18 matrix operator *(const matrix& b){ 19 matrix ans;ans.init(n,0); 20 FOR(i)FOR(j)if(mz[i][j])FOR(k) 21 ans.mz[i][k]=(ans.mz[i][k]+(LL)mz[i][j]*b.mz[j][k])%MOD; 22 return ans; 23 } 24 matrix binMat(int x); 25 }tmp[35],m; 26 matrix matrix::binMat(int x){ 27 if(!tmp_cal[0]){tmp_cal[0]=1,tmp[0].init(n,2);} 28 matrix ans;ans.init(this->n,1); 29 for(int i=0;x;x>>=1,i++){ 30 if(x&1)ans=ans*tmp[i]; 31 if(!tmp_cal[i+1])tmp_cal[i+1]=1,tmp[i+1]=tmp[i]*tmp[i]; 32 } 33 return ans; 34 } 35 //判斷是否可接的條件,或的結果為1<<8-1,與的結果中沒有連續的奇數個1 36 int cango(int p1,int p2){ 37 if((p1|p2)!=255)return 0; 38 p1=p1&p2;if(p1==255)return 1; 39 while(p1&1)p1=1<<7|(p1>>1); 40 for(int i=0,d=0;i<9;i++) 41 if(i<8&&(p1>>i)&1)d++; 42 else if(d&1)return 0; 43 return 1; 44 } 45 void dfs(int p){ 46 if(!id[p])id[p]=++ids; 47 for(int i=0;i<256;i++){ 48 if(cango(p,i)){ 49 if(id[i]==0)dfs(i); 50 dmat[id[p]][id[i]]=1; 51 } 52 } 53 } 54 void init(){ 55 ids=0; 56 dfs(255); 57 dmat[id[255]][id[255]]=2; 58 m.init(ids,2); 59 } 60 int main(){ 61 init(); 62 scanf("%d",&cas); 63 for(int ca=1;ca<=cas;ca++){ 64 scanf("%d",&n); 65 printf("Case %d: %d\n",ca,m.binMat(n).mz[1][1]); 66 } 67 }

轉載于:https://www.cnblogs.com/swm8023/archive/2012/08/29/2661259.html

總結

以上是生活随笔為你收集整理的HDU 4332 Constructing Chimney [状态压缩+矩阵]的全部內容,希望文章能夠幫你解決所遇到的問題。

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