Problem A: 方磚問題
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 6 Solved: 2
[Submit][Status][Web Board]
Description
用邊長小於N的正方形方磚(注意,不要求所有的方磚大小相同,請看樣例說明)不重疊地鋪滿N*N的正方形房間,最少要幾塊方磚。
可以將n*n的大正方形分成若干的小矩形,然後對每一個小矩形遞歸地求解,但是分塊方法應該具有普遍性,而且分塊數目應該儘量地少。最好的情況莫過於將正方形分成兩塊,對於這道題,我們可以考慮將正方形分成n*k和n*(n-k)的兩塊小矩形,每一塊都恰好被邊長小於n的正方形以最優的方式填滿(即數目最小的填充方式)。使用動態規劃法,可得遞歸方程爲:
問要鋪滿邊長爲N的正方形,需幾種方磚,使得方磚塊數最少。
Input
第一行是一個整數T,表示測試數據的組數,接下來的T 行,每一行是一個N(2<=N<=100)
Output
對於每一組測試數據輸出一行,爲最少需要的塊數。
Sample Input
2
4
5
Sample Output
4
8
HINT
最優的鋪磚方法
AABBAABBCCDDCCDD
A,B,C,D爲四塊方磚的代號。
其他的鋪法,例如:
AAABAAACAAADEFGH
需要的8塊磚,不是最少的。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define infinity 0x3f3f3f3f
using namespace std;
int a[104][105];
int slove(int n)
{
int i,j,k,t,mins;
memset(a,0,sizeof(a));
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j&&i!=n)
{
a[i][j]=1;
}
else
{
mins=infinity;
if(i<j)
{
for(k=j/2;k<=j-1;k++)
{
mins=min(mins,a[k][i]+a[j-k][i]);
}
}
else
{
for(k=i/2;k<=i-1;k++)
{
mins=min(mins,a[k][j]+a[i-k][j]);
}
}
a[j][i]=a[j][i]=mins;
}
}
}
return a[n][n];
}
int main()
{
int t,n;
cin>>t;
while(t--)
{
cin>>n;
cout<<slove(n)<<endl;
}
}