Problem description
已知3×2n个棋盘格子,试求用火柴棒覆盖所有格子的方法(一根火柴棒可覆盖2个格子)。如n=1时,有如下3种覆盖方法:
编写一个程序,试对给出的任意一个n(0<n<1000),输出铺法的总数。
Algorithm design
Developing program 动态规划
Problem analysis
和初级骨牌相差不了多少
某种意义上只是衍生的方式变了
通过观察题目的图
以两列格子为一个单位
每个单位都可以由上一个单位所有情况经过三种变换得来
但是特殊的是
可以出现像这样的情形:
也就是说 每个单位还可以由前面任意一个单位通过两种变换延伸出来(横路在最上或最下)
其实一开始讨论的
和也从属于这种情况,所以三种变换可以缩为一种
那么动规方程:
为了方便 设置一个前缀和sum
因为第一单位有三种情况 第零单位也要计入一个
那么sum初始为4
Source code
1 #include <bits/stdc++.h> 2 #define bnd 1001 3 4 using namespace std; 5 6 struct bign 7 { 8 int len,num[bnd]; 9 bign operator =(string st) 10 { 11 memset(num,0,sizeof(num)); 12 len=st.size(); 13 for(int i=0;i<len;i++) 14 num[i]=st[len-i-1]-'0'; 15 return *this; 16 } 17 bign operator =(bign eq) 18 { 19 memset(num,0,sizeof(num)); 20 len=eq.len; 21 for(int i=0;i<len;i++) 22 num[i]=eq.num[i]; 23 return *this; 24 } 25 bign operator +(bign ad) 26 { 27 bign ans; 28 ans.len=max(len,ad.len); 29 memset(ans.num,0,sizeof(ans.num)); 30 int accu=0; 31 for(int i=0;i<ans.len;i++) 32 { 33 ans.num[i]=(num[i]+ad.num[i]+accu)%10; 34 accu=(num[i]+ad.num[i]+accu)/10; 35 } 36 if(accu)ans.num[ans.len++]=accu; 37 return ans; 38 } 39 bign operator +=(bign ad) 40 { 41 *this=*this+ad; 42 return *this; 43 } 44 friend ostream& operator <<(ostream& out,bign res) 45 { 46 for(int i=res.len-1;i>=0;i--) 47 out<<res.num[i]; 48 return out; 49 } 50 }; 51 bign ans,sum; 52 int col; 53 54 int main() 55 { 56 freopen("gupai.in","r",stdin); 57 freopen("gupai.out","w",stdout); 58 cin>>col; 59 ans="3"; 60 sum="4"; 61 for(int i=2;i<=col;i++) 62 { 63 ans+=sum+sum; 64 sum+=ans; 65 } 66 cout<<ans<<endl; 67 fclose(stdin); 68 fclose(stdout); 69 return 0; 70 }
over