Tri Tiling
Total Submission(s): 2118 Accepted Submission(s): 1211
轉:::,如果n爲奇數,必然無解。
當n爲偶數時,一個比較直觀的思路就是把大矩形用豎線切出左邊一部分,然後遞歸求解,就像UVA_10359那樣,直接考慮最左邊一個小矩形是如何構成的我們就可以遞歸得到f(n)遞推式。
雖然這個題目乍看上去小矩形似乎拼法比較多,而且要拼出一個不能再用豎線切分的小矩形似乎拼的方法也並不直觀。但如果我們在紙上多畫一畫的話,對於拼任意一個橫向邊長爲x的不可再用豎線切分的小矩形,如果x爲2,顯然有3種拼法,如果x爲大於2的偶數,那麼只有2種拼法。
至於如果x>2爲什麼只有兩種拼法,我們不妨實際拼一下。首先第一列肯定只有兩種情況,第一種是一個橫的在上面,然後一個豎的在左下方,第二種是一個橫的在下面,然後一個豎的在左上方,因爲兩種情況對稱,我們只討論第一種情況。
現在已經拼好兩個了,如果橫的下面再放一個豎的,那麼顯然這個就成了一個x=2的小矩形了,那麼最後拼出來的就不符合我們前面說的不可再用豎線切分的特徵了,因此橫的下面也即豎的右邊,只能再放兩個橫的,放完兩個橫的我們就發現兩個橫的上面有一個小正方形區域,這個區域只能楔進去一個橫的,等把這個橫的畫完之後,MyGod,我們會發現一個驚人的事實,現在的這個結構是和我們最初放完一個橫的一個豎的的那種情況的結構是一樣的!因此,如果我們想繼續向右拼出不能被豎線切分的矩形,那麼只能是重複之前的操作,因而得到的最後橫向邊長爲x的矩形是唯一確定的。
前面我們最初拼的時候只取了對稱的兩種情況之一,因此,如果x>2,拼出一個不能被豎線切割的矩形的方法只有兩種。
那麼遞推公式自然就有了,f(n)=3*f(n-2)+2*f(n-4)+…+2*f(0),然後再寫出f(n-2)的遞推式後兩式作差就可以得到f(n)=4*f(n-2)-f(n-4),遞歸的邊界是f(0)=1,f(2)=4。
代碼:0MS
#include <iostream> #include <algorithm> #include <stdio.h> #include <string.h> using namespace std; #define M 31 int f[M]={1,3}; int main() { int i,n; for(i=2;i<M;i++) f[i]=4*f[i-1]-f[i-2]; while(cin>>n) { if(n<0) break; if(n%2==0) cout<<f[n/2]<<endl; else cout<<0<<endl; } return 0; }