实现的细节很多,学到了如何翻转、旋转、平移,get很多技巧,值得一做。

AC代码:

#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=10+5;
int ans[maxn][maxn][maxn];

struct animal{
    int x,y;
    animal(int x=0,int y=0):x(x),y(y){};
    bool operator < (const animal &p) const {
        return x<p.x||(x==p.x&&y<p.y);
    }
};
typedef set<animal> node;
#define For_animal(c,p) for(node::iterator c=(p).begin();c!=(p).end();++c)

inline node normalize(const node &p){  //normalize
    int minx=p.begin()->x,miny=p.begin()->y;
    For_animal(c,p){
        minx=min(minx,c->x);
        miny=min(miny,c->y);
    }
    node p2;
    For_animal(c,p){
        p2.insert(animal(c->x-minx,c->y-miny));
    }
    return p2;
}

inline node rotate(const node &p){  //rotate
    node p2;
    For_animal(c,p){
        p2.insert(animal(c->y,-c->x));
    }
    return normalize(p2);
}

inline node flip(const node &p){ //flip
    node p2;
    For_animal(c,p){
        p2.insert(animal(c->x,-c->y));
    }
    return normalize(p2);
}

const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};
set<node>poly[maxn];

void add(const node &p0,const animal &newc){ //add
    node p=p0;
    p.insert(newc);
    p=normalize(p);
    int n=p.size();
    for(int i=0;i<4;++i){
        if(poly[n].count(p)!=0) return;
        p=rotate(p);
    }
    p=flip(p);
    for(int i=0;i<4;++i){
        if(poly[n].count(p)!=0) return;
        p=rotate(p);
    }
    poly[n].insert(p);
}

void solve(){
    node s;
    s.insert(animal(0,0));
    poly[1].insert(s);

    for(int n=2;n<=10;++n){
        for(set<node>::iterator p=poly[n-1].begin();p!=poly[n-1].end();++p){
           For_animal(c,*p)     //从当前联通块开始延伸
                for(int dir=0;dir<4;++dir){
                    int newx=c->x+dx[dir],newy=c->y+dy[dir];
                    animal newc(newx,newy);
                    if(p->count(newc)==0) add(*p,newc);
                }
        }
    }

    //make answer into array
    const int len=10;
    for(int n=1;n<=len;++n)
        for(int w=1;w<=len;++w)
            for(int h=1;h<=len;++h){
                int cnt=0;
                for(set<node>::iterator p=poly[n].begin();p!=poly[n].end();++p){
                    int maxx=0,maxy=0;
                    For_animal(c,*p){
                        maxx=max(maxx,c->x);
                        maxy=max(maxy,c->y);
                    }
                    if(min(maxx,maxy)<min(w,h)&&max(maxx,maxy)<max(w,h))  //这个地方是<而不是<=的原因是坐标是从0开始
                        ++cnt;
                }
                ans[n][w][h]=cnt;
            }

}

int main(){
    solve();
    int n,w,h;
    while(scanf("%d%d%d",&n,&w,&h)==3){
        printf("%d\n",ans[n][w][h]);
    }
    return 0;
}

如有不当之处欢迎指出!

UVA1602的更多相关文章

  1. UVA-1602 Lattice Animals 搜索问题(打表+set)

    题目链接 https://vjudge.net/problem/UVA-1602 紫书的一道例题,跟之前的很多题目有很多不同. 本题不像是一般的dfs或bfs这样的搜索套路,而是另一种枚举思路. 题意 ...

  2. UVA1602 Lattice Animals 网格动物 (暴力,STL)

    多联骨牌的生成办法,维基上只找到固定的骨牌fix,而free的没有找到. 于是只好写个set判重的简单枚举了. 旋转的操作,可以在坐标轴上画个点,以原点为轴心,逆时针旋转90度,新的点的坐标为(-y, ...

  3. UVA1602 Lattice Animals 搜索+剪枝

    题目大意 给出一个$w\times h$的网格,定义一个连通块为一个元素个数为$n$的方格的集合$A,\forall x\in A, \exists y\in A$,使得$x,y$有一条公共边.现要求 ...

  4. 【例题 7-14 UVA-1602】Lattice Animals

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 借鉴网上的题解的. 思路是. 用"标准化"的思想. 确定基准点(0,0) 然后假设(0,0)是第一个连通块. 然 ...

  5. 网格动物UVA1602

    题目大意 输入n,w,h(1<=n<=10,1<=w,h<=n).求能放在w*h网格里的不同的n连块的个数(平移,旋转,翻转算一种) 首先,方法上有两个,一是打表,dfs构造连 ...

  6. UVa 1602 网格动物(回溯)

    https://vjudge.net/problem/UVA-1602 题意:计算n连通块不同形态的个数. 思路: 实在是不知道该怎么做好,感觉判重实在是太麻烦了. 判重就是判断所有格子位置是否都相同 ...

随机推荐

  1. jquery取前、后、父、子元素

    前.prev(); 后.next(); 父.parent(); 子.children(); 注意:前的前是.prev().prev(),例如前元素无i,但前的前的i元素有i,不能写成.prev('i' ...

  2. Oracle多行记录合并的几种方法

    今天正好遇到需要做这个功能,顺手搜了一下网络,把几种方法都列出来,方便以后参考. 1 什么是合并多行字符串(连接字符串)呢,例如: SQL> desc test; Name Type Nulla ...

  3. 《剑指offer》数组中出现次数超过数组长度一半的数字

    题目: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2.如 ...

  4. 20165220 学习基础和C语言基础调查

    # # # # 我觉得我打游戏(不知道算不算一技之长)毕竟从小学一年级就接触到了各种形形色色的游戏,讲道理其实我的游戏天赋毕竟还是很大的,从意识到感觉我觉得都比大多数人好一些,其实吧打游戏打得好也是很 ...

  5. PHP实现QQ登录的开发教程

    第三方登录,就是使用大家比较熟悉的比如QQ.微信.微博等第三方软件登录自己的网站,这可以免去注册账号.快速留住用户的目的,免去了相对复杂的注册流程.下边就给大家讲一下怎么使用PHP开发QQ登录的功能. ...

  6. IIS使用十大原则,(IIS过期时间,IIS缓存设置) 【转载】

    1. 自定义错误页虽然自定义错误页很简单,但只有少数管理员有效地利用了它.管理员可以在MMC中将HTTP错误信息映像到服务器上的绝对URL或是某个文件,更为详细的信息可以在这里找到.如果你嫌这太麻烦, ...

  7. java 网络编程之UDP通信和简单的群聊程序

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  8. Gitlab权限管理-issue管理[六]

    标签(linux): git 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 设置好密码后登录进入管理目录 创建组 设置组名和权限 创建用户 已有四个用户了 给p ...

  9. 单元测试系列:Mock工具之Mockito实战

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6780719.html 在实际项目中写单 ...

  10. 在ubuntu系统中给filezilla创建桌面快捷方式

    filezilla是一款开源的ftp客户端,当然他们也有服务端,这里以filezilla客户端为例创建快捷方式!默认情况下,ubuntu将自动安装的软件快捷方式保存在/usr/share/applic ...