UVA1602 Lattice Animals 网格动物 (暴力,STL)
多联骨牌的生成办法,维基上只找到固定的骨牌fix,而free的没有找到。
于是只好写个set判重的简单枚举了。
旋转的操作,可以在坐标轴上画个点,以原点为轴心,逆时针旋转90度,新的点的坐标为(-y,x)。顺时针也差不多。
反转类似。
对于操作完的骨牌,还要进行标准化,取最小的横纵坐标为参考,求出新的坐标,以便于判断。
生成所有骨牌以后,预处理一下(一顿乱搞)就好了。
#include<bits/stdc++.h> using namespace std; #define local const int maxn = 11; struct Cell { int x,y; Cell(int x = 0,int y = 0):x(x),y(y){} bool operator < (const Cell & rhs) const { return x < rhs.x||(x == rhs.x && y < rhs.y); } }; #define FOR_CELL(c, p) for(Polyomino::const_iterator c = (p).begin(); c != (p).end(); ++c) typedef set<Cell> Polyomino; inline void normalize(Polyomino *px){ int minx = px->begin()->x, miny = px->begin()->y; Polyomino::const_iterator c; for(c = px->begin(); c != px->end(); ++c) { minx = min(minx, c->x); miny = min(miny, c->y); } Polyomino pn; for(c = px->begin(); c != px->end(); ++c){ pn.insert(Cell(c->x-minx,c->y-miny)); } *px = pn; } inline void Rotate(Polyomino & px) { Polyomino p2; Polyomino::const_iterator c; for(c = px.begin(); c != px.end(); ++c) p2.insert(Cell(c->y,-c->x)); px = p2; normalize(&px); } inline void flip(Polyomino &px) { Polyomino p3; Polyomino::const_iterator c; for(c = px.begin(); c != px.end(); ++c) p3.insert(Cell(-c->x,c->y)); normalize(&p3); px = p3; } set<Polyomino>poly[maxn]; void check(const Polyomino &p0,Cell& newCell){ Polyomino p = p0; p.insert(newCell); normalize(&p); int n = p.size(); for(int i = 0; i < 4; i++){ if(poly[n].count(p)) return; Rotate(p); } flip(p); for(int i = 0; i < 4; i++){ if(poly[n].count(p)) return; Rotate(p); } poly[p.size()].insert(p); } int ans[maxn][maxn][maxn]; struct whc { int w,h,c; whc(){} whc(int w,int h,int c):w(w),h(h),c(c){} }; int SIZE[maxn] = {0}; whc V[maxn][17]; void generatePoly(){ const int dx[] = {0,0,1,-1}; const int dy[] = {1,-1,0,0}; Polyomino s; s.insert(Cell(0,0)); poly[1].insert(s); for(int i = 1; i < maxn-1; i++){ for(set<Polyomino>::iterator it = poly[i].begin(); it != poly[i].end(); it++ ){ FOR_CELL(c,*it){ for(int dir = 0; dir < 4; dir++){ Cell newc(c->x+dx[dir],c->y+dy[dir]); if(it->count(newc) == 0) check(*it,newc); } } } } int mp[maxn][maxn][maxn] = {0}; for(int n = 1; n < maxn; n++){ SIZE[n] = 0; for(set<Polyomino>::iterator it = poly[n].begin(); it != poly[n].end(); it++ ){ int maxx,maxy; maxx = maxy = 0; FOR_CELL(c,*it){ maxx = max(maxx,c->x); maxy = max(maxy,c->y); } if(maxy<maxx) swap(maxx,maxy); mp[n][maxx][maxy]++; } } for(int n = 1; n < maxn; n++){ for(int w = 0; w < n; w++) for(int h = w; h < n; h++){ if(mp[n][w][h]){ V[n][SIZE[n]++] = whc(w,h,mp[n][w][h]); } } } } inline int ANS(int n,int w,int h){ if(~ans[n][w][h]) return ans[n][w][h]; else { int cnt = 0; whc *a = V[n]; for(int i = 0, sz =SIZE[n] ; i < sz; i++ ){ whc & u = a[i]; if(u.w < w && u.h < h) cnt += u.c; } return ans[n][w][h] = cnt; } } int main() { #ifdef local freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif // local generatePoly(); memset(ans,-1,sizeof(ans)); int n,w,h; while(~scanf("%d%d%d",&n,&w,&h)){ if(h<w) swap(w,h); printf("%d\n",ANS(n,w,h)); } return 0; }