思路:
dfs。
搜索时,每一次都在上一次的图形上加一个方块,具体方法是遍历上一次的图形,在每一个方块的上下左右都尝试放一个方块。
每次搜得一个图形,就将它化为一个标准型式,即整个图形都在第一象限且过原点。然后将这个新的图形翻折、旋转,并把这些变形存进一个set里便于判重。
注意:
只需搜索一次,处理出所有权情况并打表,这可以节省不少时间。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<sstream>
#include<queue>
#include<set>
using namespace std;
#define maxn 10
struct Node {
int x,y;
Node() {
x=0,y=0;
}
Node(int one,int two) {
x=one,y=two;
}
bool operator < (const Node& other) const {
if(x<other.x||(x==other.x&&y<other.y)) return true;
return false;
}
Node Place(int a,int b) {
return Node(x+a,y+b);
}
};
struct Block {
set<Node> Set;
void insert(Node y) {
Set.insert(y);
}
bool operator < (const Block& other) const {
if(Set.size()<other.Set.size()) return true;
if(Set.size()>other.Set.size()) return false;
vector<Node> one,two;
for(set<Node>::iterator it=Set.begin(); it!=Set.end(); it++) {
one.push_back(*it);
}
for(set<Node>::iterator it=other.Set.begin(); it!=other.Set.end(); it++) {
two.push_back(*it);
}
for(int i=0; i<one.size(); i++) {
if(one[i]<two[i]) return true;
if(two[i]<one[i]) return false;
}
return false;
}
};
set<Block> Use;
int f[maxn+5][maxn+5][maxn+5]= {0};
Block ToStd(Block x) {
int minx=maxn+5,miny=maxn+5;
for(set<Node>::iterator it=x.Set.begin(); it!=x.Set.end(); it++) {
Node y=(*it);
minx=min(minx,y.x);
miny=min(miny,y.y);
}
Block Standard;
for(set<Node>::iterator it=x.Set.begin(); it!=x.Set.end(); it++) {
Node y=(*it);
y.x-=minx;
y.y-=miny;
Standard.Set.insert(y);
}
return Standard;
}
Block miro(Block x) {
Block Standard;
for(set<Node>::iterator it=x.Set.begin(); it!=x.Set.end(); it++) {
Node y=(*it);
y.y=0-y.y;
Standard.Set.insert(y);
}
return ToStd(Standard);
}
Block Turn(Block x) {
Block Standard;
for(set<Node>::iterator it=x.Set.begin(); it!=x.Set.end(); it++) {
Node y=(*it);
int t=y.x;
y.x=y.y;
y.y=0-t;
Standard.Set.insert(y);
}
return ToStd(Standard);
}
Node Measure(Block x) {
int maxX=0,maxY=0;
for(set<Node>::iterator it=x.Set.begin(); it!=x.Set.end(); it++) {
Node y=(*it);
maxX=max(maxX,y.x);
maxY=max(maxY,y.y);
}
return Node(maxX+1,maxY+1);
}
void make(int step,Block x) {
if(step>maxn) return ;
Block y=x;
if(Use.find(y)!=Use.end()) return ;
for(int i=1; i<=4; i++) {
y=Turn(y);
Use.insert(y);
}
y=miro(y);
for(int i=1; i<=4; i++) {
y=Turn(y);
Use.insert(y);
}
Node m=Measure(y);
bool a[maxn+5][maxn+5]={0};
for(int i=m.x;i<=maxn;i++){
for(int j=m.y;j<=maxn;j++){
a[i][j]=a[j][i]=true;
}
}
for(int i=1;i<=maxn;i++){
for(int j=1;j<=maxn;j++){
f[step][i][j]+=a[i][j];
}
}
int M1[5]= {0,1,-1,0,0};
int M2[5]= {0,0,0,1,-1};
for(set<Node>::iterator it=x.Set.begin(); it!=x.Set.end(); it++) {
Node y=(*it);
for(int i=1; i<=4; i++) {
Block New=x;
New.insert(y.Place(M1[i],M2[i]));
if(New.Set.size()!=x.Set.size()) {
New=ToStd(New);
make(step+1,New);
}
}
}
}
void init() {
Use.clear();
}
int main() {
init();
Block x;
x.insert(Node());
make(1,x);
int n,w,h;
while(~scanf("%d%d%d",&n,&w,&h)) {
printf("%d\n",f[n][w][h]);
}
return 0;
}