题目链接

题意:求能放进w*h的网格中的不同的n连通块个数(通过平移/旋转/翻转后相同的算同一种),1<=n<=10,1<=w,h<=n。

刘汝佳的题真是一道比一道让人自闭...QAQ~~

这道题没什么好的办法,Polya定理也毫无用武之地,只能暴力构造出所有可能的连通块,然后用set判重,比较考验基本功。

连通块可以用一个结构体D来表示,D的n代表黑块数量,然后有至多10个点P(x,y),用另一个结构体数组P[N]来表示。

问题的关键在于如何判重。

首先要知道set是通过<运算符来判重的,因此肯定要重载一下<运算符。既然要重载<运算符,那么就需要能比较出两个连通块的大小来。

如何比较两个黑块数量相同的连通块的大小呢?可以类比向量的字典序大小比较法,把所有的黑块按照x从小到大排序,x相同的按y从小到大排序,就可以比较大小了。

但是同构的两个连通块之间是不具有大小关系的,因此要先想办法把同构的连通块弄成统一的样子。

考虑三类等价变换:

1.平移:$(x,y)\leftrightarrow(x+a,y+b)$

2.旋转:$(x,y)\leftrightarrow(-y,x)$

3.翻转:$(x,y)\leftrightarrow(-x,y)$

所有同构的连通块都可以通过以上三类变换相互得到,对于同构的连通块,可以只保留其中字典序最小的。由于通过旋转和翻转能构造出的不同连通块只有8种,因此可以枚举这8中连通块,然后平移到左上角,取其中字典序最小的即可。

注意在比较字典序的时候,正反都要比较一下。(某人因为忘了反着比较而花了两个小时写了一整页代码来debug~~)

然后就没什么特别需要注意的了,设st[i][j][k]为用i个黑块能构造出j*k(j<=k)的异构连通块的集合,递推搞一搞就行了。

代码:(七重for循环,大概是我写过的层数最多的for循环了~~UVA的评测机也很给力,本地要跑300+ms,交上去30ms就过了)

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=+,inf=0x3f3f3f3f;
const int dx[]= {,,-,};
const int dy[]= {-,,,};
//格点
struct P {
int x,y;
bool operator==(const P& b)const {return x==b.x&&y==b.y;}
bool operator<(const P& b)const {return x!=b.x?x<b.x:y<b.y;}
};
//连通块
struct D {
int n;
P p[N];
D(int _n):n(_n) {}
//字典序比较,重点
bool operator<(const D& b)const {
for(int i=; i<n; ++i) {
if(p[i]<b.p[i])return ;
if(b.p[i]<p[i])return ;
}
return ;
}
//旋转
D rot() {
D ret(n);
for(int i=; i<n; ++i)ret.p[i]= {-p[i].y,p[i].x};
return ret;
}
//翻转
D flip() {
D ret(n);
for(int i=; i<n; ++i)ret.p[i]= {-p[i].x,p[i].y};
return ret;
}
//平移到左上角
D norm() {
D ret=*this;
int dx=inf,dy=inf;
for(int i=; i<n; ++i)dx=min(dx,ret.p[i].x),dy=min(dy,ret.p[i].y);
for(int i=; i<n; ++i)ret.p[i].x-=dx,ret.p[i].y-=dy;
sort(ret.p,ret.p+n);
return ret;
}
//字典序最小的同构
D minimum() {
D a=this->norm(),b=a;
for(int i=; i<; ++i,b=b.flip())
for(int j=; j<; ++j,b=b.rot()) {
b=b.norm();
if(b<a)a=b;
}
return a;
}
};
set<D> st[N][N][N];
int n,w,h,ans; int main() {
D t();
t.p[]= {,};
st[][][].insert(t);
for(int _=; _<; ++_) {
for(int i=; i<=; ++i)
for(int j=i; j<=; ++j) {
for(D t:st[_][i][j]) {
t.n++;
for(int k=; k<t.n-; ++k) {
for(int f=; f<; ++f) {
t.p[t.n-]= {t.p[k].x+dx[f],t.p[k].y+dy[f]};
bool ff=;
for(int l=; l<t.n-; ++l)if(t.p[t.n-]==t.p[l]) {ff=; break;}//防止格点重复
if(!ff)continue;
int maxx=~inf,minx=inf,maxy=~inf,miny=inf;
for(int l=; l<t.n; ++l) {
maxx=max(maxx,t.p[l].x);
minx=min(minx,t.p[l].x);
maxy=max(maxy,t.p[l].y);
miny=min(miny,t.p[l].y);
}
int tx=maxx-minx+,ty=maxy-miny+;
if(tx>ty)swap(tx,ty);
st[_+][tx][ty].insert(t.minimum());
}
}
}
}
}
while(scanf("%d%d%d",&n,&w,&h)==) {
ans=;
if(w>h)swap(w,h);
for(int i=; i<=w; ++i)
for(int j=; j<=h; ++j)
ans+=st[n][i][j].size();
printf("%d\n",ans);
}
return ;
}

UVA - 1602 Lattice Animals (暴力+同构判定)的更多相关文章

  1. UVA 1602 Lattice Animals

    题目 输入n.w.h($1\leqslant n \leqslant 10, 1\leqslant w,h \leqslant n$),求能放在w*h网格里的不同的n连块的个数(注意,平移.旋转.翻转 ...

  2. UVa 1602 Lattice Animals (STL && 生成n连块 && 无方向形状判重)

    题意 : 给定一个 w * h 的 矩阵,在矩阵中找不同n个连通块的个数(旋转,翻转,平移算作一种) 分析 : 这题的关键点有两个 ① 生成n连块并且存储起来(因为题目是多测试用例,如果每一次都重新生 ...

  3. 【DFS】【打表】Lattice Animals

    [ZOJ2669]Lattice Animals Time Limit: 5 Seconds      Memory Limit: 32768 KB Lattice animal is a set o ...

  4. UVA 11768 - Lattice Point or Not(数论)

    UVA 11768 - Lattice Point or Not option=com_onlinejudge&Itemid=8&page=show_problem&categ ...

  5. UVA.12716 GCD XOR (暴力枚举 数论GCD)

    UVA.12716 GCD XOR (暴力枚举 数论GCD) 题意分析 题意比较简单,求[1,n]范围内的整数队a,b(a<=b)的个数,使得 gcd(a,b) = a XOR b. 前置技能 ...

  6. UVA.10305 Maximum Product (暴力)

    UVA.10305 Maximum Product (暴力) 题意分析 直接枚举起点和重点,然后算出来存到数组里面,sort然后取最大值即可. 代码总览 #include <iostream&g ...

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

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

  8. uva 725 Division(暴力模拟)

    Division 紫书入门级别的暴力,可我还是写了好长时间 = = [题目链接]uva 725 [题目类型]化简暴力 &题解: 首先要看懂题意,他的意思也就是0~9都只出现一遍,在这2个5位数 ...

  9. UVA 11080 - Place the Guards(二分图判定)

    UVA 11080 - Place the Guards 题目链接 题意:一些城市.之间有道路相连,如今要安放警卫,警卫能看守到当前点周围的边,一条边仅仅能有一个警卫看守,问是否有方案,假设有最少放几 ...

随机推荐

  1. django-admin 设计User外键,设计model

    设置外键 class profile_user(AbstractBaseUser, PermissionsMixin): company = models.ForeignKey(Company, de ...

  2. 通用TryParse

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Refle ...

  3. OS X 与传统Unix的一点区别

    在传统的Unix系统或者Linux系统中,你是很难在根目录下找到大写开头的文件夹的, 但是看一下OS X: ls / Applications Users etc private var Develo ...

  4. api token

    具体实现如下: 1. api请求客户端想服务器端一次发送用用户认证信息(用户名和密码),服务器端请求到改请求后,验证用户信息是否正确. 如果正确:则返回一个唯一不重复的字符串(一般为UUID),然后在 ...

  5. ubuntu 12.04.2 基于 L3.0.35_1.1.0_121218_source LTIB 问题汇总

    1)解压L3.0.35_1.1.0_121218_source.tar.gz 2)cd  L3.0.35_1.1.0_121218_source ,执行./install 3)  复制 patch-l ...

  6. SOA 面向服务架构 阅读笔记(一)

    Service Oriented Architecture 面向服务架构 学习笔记(一) 1.业务自由 1.1  在很多企业中,业务和IT技术是各自独立的,无法使用通用的统一语言进行管理. 1.2  ...

  7. 跨平台移动开发 App-Framework DEMO 演示

    穿越到2015 回到->MarkFan的程序员客栈 App-Framework   DEMO 演示 点击APK包下载 点击Demo代码下载 官方网站 :http://app-framework- ...

  8. INSPIRED启示录 读书笔记 - 第35章 情感接纳曲线

    技术接纳曲线 涉及了技术创新者.尝鲜者.早期消费大众.后期消费大众和跟随者,很少有产品能越过鸿沟——获得尝鲜者以外消费者的青睐 不同类型的用户具有不同的情感需求,除了技术接纳曲线模型描述用户外,还应该 ...

  9. Whitewidow:SQL 漏洞自动扫描工具

    Whitewidow 是一个开源的 SQL 漏洞自动扫描器,可用通过文件列表运行,或者从 Google 爬取并发现有潜在漏洞的网站. 这个工具支持自动格式化文件.随机用户代理.IP 地址.服务器信息. ...

  10. 网络安全-跨站脚本攻击XSS(Cross-Site Scripting)

    一.XSS攻击简介 作为一种HTML注入攻击,XSS攻击的核心思想就是在HTML页面中注入恶意代码,而XSS采用的注入方式是非常巧妙的. 在XSS攻击中,一般有三个角色参与:攻击者.目标服务器.受害者 ...