今天看了星际穿越,真心碉堡了,目前为止看过最好的科幻电影
题意:
3*n的方格,用1*2的长方条铺满,有多少中方法。
Input
Input consists of several test cases followed by a line containing -1. Each test case is a line containing an integer 0 <= n <= 30.
Output
For each test case, output one integer number giving the number of possible tilings.
动归想了半天我靠。。。一直在想二维空间递推,即使知道想不出来了还是在想,其实用一维DP,讨论最后一列位置以及最后一列的情况(最后一列之前的全部填满),然后很简单就有了一个从i-1位置推到i位置的状态转移方法,但是这个状态有2^3种,其实这个题生写也还好,但是如果行数进一步扩大,就不行了。
所以说递推矩阵用DFS写,写了好久喔,好久不写搜索了喔,搜索王跟我不一队了喔,赶紧多练练喔。
特判n=0还写错了WA一次喔。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int dfs(int loc,int x,int y,int tgt){
if(loc==6){
if(y==tgt) return 1;
return 0;
}
int ret=0;
if(loc<3){
if(x&(1<<loc)) return dfs(loc+1,x,y,tgt);
if(tgt&(1<<loc))
ret+=dfs(loc+1,x|(1<<loc),y|(1<<loc),tgt);
if(loc<2&&!(x&(1<<(loc+1))))
ret+=dfs(loc+1,(x|(1<<loc))|(1<<(loc+1)),y,tgt);
}
else{
ret+=dfs(loc+1,x,y,tgt);
if(loc<5&&!(y&(1<<(loc-3)))&&!(y&(1<<(loc-2)))&&(tgt&(1<<(loc-3)))&&(tgt&(1<<(loc-2))))
ret+=dfs(loc+1,x,(y|(1<<(loc-3)))|(1<<(loc-2)),tgt);
}
return ret;
}
struct matrix{
int a[10][10];
matrix(){memset(a,0,sizeof(a));}
matrix operator * (const matrix& in)const{
matrix ret;
for(int i=0;i<10;++i)
for(int j=0;j<10;++j)
for(int k=0;k<10;++k)
ret.a[i][j]+=a[i][k]*in.a[k][j];
return ret;
}
void set(){
for(int i=0;i<8;++i)
for(int j=0;j<8;++j)
a[j][i]=dfs(0,i,0,j);
for(int i=0;i<8;++i){
a[i][0]-=a[i][3]+a[i][6];
a[i][1]-=a[i][7];
a[i][4]-=a[i][7];
}
}
matrix quick_power(int n){
if(n==1) return *this;
matrix tem=quick_power(n/2);
if(n%2) return tem*tem*(*this);
return tem*tem;
}
}trans,ans,b;
int n;
int main(){
trans.set();
memset(b.a,0,sizeof(b.a));
b.a[7][0]=1;
while(scanf("%d",&n)!=EOF&&n!=-1){
if(!n){
puts("1");
continue;
}
ans=trans.quick_power(n)*b;
printf("%d\n",ans.a[7][0]);
}
return 0;
}