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;
}
}