UVA题目链接 sdoj题目链接
代码参考了大佬博客
比赛时想到了怎么判重,但是有些细节地方不好写,考场暴力居然打了50……
#include<cstdio>
#include<set>
#include<algorithm>
#define _rep(i,a,b) for(int i=(a);i<=(b);i++)
#define _for(i,a,b) for(int i=(a);i<(b);i++)
using namespace std;
int ans[15][15][15];
struct node{//定义一个格子
int x,y;
node(int _x,int _y){x=_x,y=_y;}
bool operator <(const node&rhs)const{
return x<rhs.x||(x==rhs.x&&y<rhs.y);}
};
const int dx[]={1,-1,0,0};
const int dy[]={0,0,1,-1};
set<node>pos;//保存方案
set<set<node> >poss[15];//pos[i]存体积为i的情况
set<node> Move(const set<node>&tmp)//全部平移到左上角
{
set<node>ret;
int minx=tmp.begin()->x;
int miny=tmp.begin()->y;
for(set<node>::iterator it=tmp.begin();it!=tmp.end();it++)
minx=min(minx,it->x),miny=min(miny,it->y);
for(set<node>::iterator it=tmp.begin();it!=tmp.end();it++)
ret.insert(node(it->x-minx,it->y-miny));
return ret;
}
set<node> Rotate(const set<node>&tmp)//旋转
{
set<node>ret;
for(set<node>::iterator it=tmp.begin();it!=tmp.end();it++)
ret.insert(node(it->y,-(it->x)));
return Move(ret);
}
set<node> Flip(const set<node>&tmp)//翻转
{
set<node>ret;
for(set<node>::iterator it=tmp.begin();it!=tmp.end();it++)
ret.insert(node(it->x,-(it->y)));
return Move(ret);
}
void dfs(const set<node>&s,const node&tmp)
{
set<node>newnode=s;
newnode.insert(tmp);
newnode=Move(newnode);
_for(i,0,4)//4次翻转
{
if(poss[newnode.size()].count(newnode))return;//这种情况已经存在了
newnode=Rotate(newnode);
}
newnode=Flip(newnode);
_for(i,0,4)
{
if(poss[newnode.size()].count(newnode))return;
newnode=Rotate(newnode);
}
poss[newnode.size()].insert(newnode);
}
void Init()
{
pos.insert(node(0,0));
poss[1].insert(pos);
_rep(k,2,10)//枚举体积为k的情况
for(set<set<node> >::iterator its=poss[k-1].begin();its!=poss[k-1].end();its++)//先取出每种k-1体积的姿势
for(set<node>::iterator it=(*its).begin();it!=(*its).end();it++)//枚举里面的方格
_for(i,0,4)
{
int nx=it->x+dx[i];
int ny=it->y+dy[i];
node tmp(nx,ny);
if(!its->count(tmp))dfs(*its,tmp);
}
_rep(k,1,10)_rep(m,1,10)_rep(n,1,10)
{
int cnt=0;
for(set<set<node> >::iterator its=poss[k].begin();its!=poss[k].end();its++)
{
int maxx=0,maxy=0;
for(set<node>::iterator it=(*its).begin();it!=(*its).end();it++)
maxx=max(maxx,it->x),maxy=max(maxy,it->y);
if(min(maxx,maxy)<min(m,n)&&max(maxx,maxy)<max(m,n))
cnt++;//放得下
}
ans[k][m][n]=cnt;
}
}
int main()
{
int m,n,k;
Init();
while(~scanf("%d%d%d",&k,&m,&n))
printf("%d\n",ans[k][m][n]);
return 0;
}