【POJ】2170 Lattice Animals
1. 题目描述
给定$n \times m, n、m \in [1, 10]$的方格,求不同形状的$[1 \cdots 10]$联通块的个数?
所谓不同形状,表示不能通过平移、旋转、镜像实现相同的形状。
2. 基本思路
显然数据不大, 那么可以打表。首先考虑,这个表怎么打?不妨使用$cn$表示连通块数。
那么对于$n \times m, m、n \ge cn$的种类数与$cn \times cn$中$cn$连通块数完全相同。
否则搜索$cn \times cn$中$cn$中的连通块,找出那些在边界$n \times m$的数量即可。
那么,关键问题是怎么对连通块抽象,怎么进行状态压缩。显然存在着平移、旋转、镜像等操作。
这也意味着同一个连通块的表达形式可能不同。
这里采用正则化的思想,即找到$x,y$的最小值,然后对所有坐标减去这个值。然后在对坐标值排序。
即可以得到标准化的连通块。那么如何状态压缩呢?
对排好序的连通块的$x,y$进行压缩,因此pair<int,int>即可以表示一个连通块,使用map充当visit。
假定我们已经得到了$cn \times cn$中$n-1$连通的情况,那么对其中的每个块向四个方向拓展既可以得到所有$n$连通的情况。
这里,首先注意边界范围不能超过$cn \times cn$,同时,仅考虑镜像和旋转得到的状态visit中是否包含。
平移不用考虑是因为使用了正则化,大大减少了计算量。
3. 代码
(1) 打表代码,其实不打表也能过
/* 2170 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
#define INF 0x3f3f3f3f
#define mset(a, val) memset(a, (val), sizeof(a)) #define LL unsigned long long typedef struct node_t {
vpii vp; void sorted() {
sort(all(vp));
} void push_back(pii p) {
vp.pb(p);
} void clear() {
vp.clr();
} int size() const {
return vp.size();
} void regular() {
int mnx = INT_MAX, mny = INT_MAX; int sz = SZ(vp); rep(i, , sz) {
mnx = min(vp[i].fir, mnx);
mny = min(vp[i].sec, mny);
} rep(i, , sz) {
vp[i].fir -= mnx;
vp[i].sec -= mny;
}
} pair<pii,pii> calBound() const {
int mnx, mny, mxx, mxy;
int sz = SZ(vp); if (sz == )
return mp(mp(, ), mp(,)); mnx = mny = INT_MAX;
mxx = mxy = INT_MIN;
rep(i, , sz) {
mnx = min(mnx, vp[i].fir);
mxx = max(mxx, vp[i].fir);
mny = min(mny, vp[i].sec);
mxy = max(mxy, vp[i].sec);
} return mp(mp(mnx, mxx), mp(mny, mxy));
} pii calL() const {
pair<pii,pii> ppii = calBound();
return mp(ppii.fir.sec-ppii.fir.fir+, ppii.sec.sec-ppii.sec.fir+);
}
} node_t; const int maxn = ;
vector<node_t> E[maxn][maxn];
set<pair<LL,LL> > has;
int ans[maxn][maxn][maxn];
int dir[][] = {
-, , ,, ,-, ,
};
int n, m, cn;
bool printInfo = false; pair<LL,LL> zip(const node_t& d, int sz) {
node_t nd = d;
LL x = , y = ; nd.regular();
nd.sorted(); rep(i, , sz) {
x = * x + nd.vp[i].fir;
y = * y + nd.vp[i].sec;
} return mp(x, y);
} void unzip(pair<LL,LL> p, node_t& nd, int sz) {
LL &x = p.fir, &y = p.sec; per(i, , sz) {
nd.vp[i].fir = x % ;
nd.vp[i].sec = y % ;
x /= ;
y /= ;
}
} bool check(const node_t& b) {
pair<LL,LL> p = zip(b, cn); return has.find(p) != has.end();
} void rotate(node_t& d) {
rep(i, , cn) {
swap(d.vp[i].fir, d.vp[i].sec);
d.vp[i].sec = -d.vp[i].sec;
}
} void mirror(node_t& d) {
rep(i, , cn)
d.vp[i].fir = -d.vp[i].fir;
} bool judge(node_t& d) {
rep(i, , cn) {
rep(j, i+, cn) {
if (d.vp[i] == d.vp[j])
return false;
}
} node_t dd; dd = d; rep(i, , ) {
rep(j, , ) {
if (check(dd))
return false;
rotate(dd);
}
mirror(dd);
} return true;
} int calc() {
if (n>=cn && m>=cn)
return SZ(E[cn][cn]); const vector<node_t>& vc = E[cn][cn];
int sz = SZ(vc);
int ret = ; rep(i, , sz) {
pair<pii,pii> ppii = vc[i].calBound();
int lx = ppii.fir.sec - ppii.fir.fir + ;
int ly = ppii.sec.sec - ppii.sec.fir + ;
if ((lx<=n && ly<=m) || (lx<=m && ly<=n))
++ret;
} return ret;
} void printAns() {
puts("int ans[10][100] = {");
rep(i, , ) {
putchar('\t');
putchar('{');
rep(j, , ) {
rep(k, , ) {
if (j== && k==)
printf("%d", ans[i][j][k]);
else
printf(",%d", ans[i][j][k]);
}
}
putchar('}');
if (i != )
putchar(',');
putchar('\n');
}
puts("};");
} void solve() {
vector<node_t>& vc = E[n][cn];
const vector<node_t>& ovc = E[n][cn-]; has.clr();
int osz = SZ(ovc); rep(i, , osz) {
const node_t& nd = ovc[i];
pair<pii,pii> ppii = nd.calBound();
int mxx, mxy, mnx, mny; node_t d; rep(j, , cn-) d.pb(nd.vp[j]);
d.pb(mp(, )); rep(j, , cn-) {
const int& x = nd.vp[j].fir;
const int& y = nd.vp[j].sec;
int xx, yy; rep(k, , ) {
xx = x + dir[k][];
yy = y + dir[k][];
d.vp[cn-].fir = xx;
d.vp[cn-].sec = yy; mnx = min(ppii.fir.fir, xx);
mxx = max(ppii.fir.sec, xx);
mny = min(ppii.sec.fir, yy);
mxy = max(ppii.sec.sec, yy); if (mxx-mnx+>n || mxy-mny+>n)
continue; if (judge(d)) {
vc.pb(d);
pair<LL, LL> p = zip(d, cn);
has.insert(p);
}
}
}
}
} void init() {
for (n=; n<maxn; ++n) {
for (cn=; cn<maxn; ++cn) {
if (cn == ) {
node_t nd;
nd.pb(mp(, ));
E[n][cn].pb(nd);
} else if (cn < n) {
int sz = SZ(E[cn][cn]);
rep(i, , sz)
E[n][cn].pb(E[cn][cn][i]);
} else {
solve();
} printf("E[%d][%d] = %d\n", n, cn, SZ(E[n][cn]));
fflush(stdout);
}
} for (cn=; cn<=; ++cn) {
for (n=; n<=cn; ++n) {
for (m=n; m<=cn; ++m) {
ans[cn][n][m] = ans[cn][m][n] = calc();
}
}
} printAns();
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif init(); #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}
(2) AC程序
/* 2170 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
#define INF 0x3f3f3f3f
#define mset(a, val) memset(a, (val), sizeof(a)) int ans[][] = {
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,}
}; int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int n, w, h; while (scanf("%d%d%d",&n,&w,&h)!=EOF) {
--n;
--w;
--h;
cout << ans[n][w*+h] << endl;
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}
4. 数据生成器
import sys
import string
from random import randint, shuffle def GenData(fileName):
with open(fileName, "w") as fout:
t = 1
for tt in xrange(t):
for j in xrange(1, 11):
for i in xrange(1, j+1):
for k in xrange(1, j+1):
fout.write("%d %d %d\n" % (j, i, k)) def MovData(srcFileName, desFileName):
with open(srcFileName, "r") as fin:
lines = fin.readlines()
with open(desFileName, "w") as fout:
fout.write("".join(lines)) def CompData():
print "comp"
srcFileName = "F:\Qt_prj\hdoj\data.out"
desFileName = "F:\workspace\cpp_hdoj\data.out"
srcLines = []
desLines = []
with open(srcFileName, "r") as fin:
srcLines = fin.readlines()
with open(desFileName, "r") as fin:
desLines = fin.readlines()
n = min(len(srcLines), len(desLines))-1
for i in xrange(n):
ans2 = int(desLines[i])
ans1 = int(srcLines[i])
if ans1 > ans2:
print "%d: wrong" % i if __name__ == "__main__":
srcFileName = "F:\Qt_prj\hdoj\data.in"
desFileName = "F:\workspace\cpp_hdoj\data.in"
GenData(srcFileName)
MovData(srcFileName, desFileName)
【POJ】2170 Lattice Animals的更多相关文章
- 【POJ】1704 Georgia and Bob(Staircase Nim)
Description Georgia and Bob decide to play a self-invented game. They draw a row of grids on paper, ...
- 【POJ】1067 取石子游戏(博弈论)
Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后 ...
- 【BZOJ】【1986】【USACO 2004 Dec】/【POJ】【2373】划区灌溉
DP/单调队列优化 首先不考虑奶牛的喜欢区间,dp方程当然是比较显然的:$ f[i]=min(f[k])+1,i-2*b \leq k \leq i-2*a $ 当然这里的$i$和$k$都是偶数啦~ ...
- 【POJ】【2104】区间第K大
可持久化线段树 可持久化线段树是一种神奇的数据结构,它跟我们原来常用的线段树不同,它每次更新是不更改原来数据的,而是新开节点,维护它的历史版本,实现“可持久化”.(当然视情况也会有需要修改的时候) 可 ...
- 【CodeForces】713 D. Animals and Puzzle 动态规划+二维ST表
[题目]D. Animals and Puzzle [题意]给定n*m的01矩阵,Q次询问某个子矩阵内的最大正方形全1子矩阵边长.n,m<=1000,Q<=10^6. [算法]动态规划DP ...
- 【POJ】1222 EXTENDED LIGHTS OUT
[算法]高斯消元 [题解] 高斯消元经典题型:异或方程组 poj 1222 高斯消元详解 异或相当于相加后mod2 异或方程组就是把加减消元全部改为异或. 异或性质:00 11为假,01 10为真.与 ...
- 【POJ】2892 Tunnel Warfare
[算法]平衡树(treap) [题解]treap知识见数据结构 在POJ把语言从G++换成C++就过了……??? #include<cstdio> #include<algorith ...
- 【POJ】【1637】Sightseeing tour
网络流/最大流 愚人节快乐XD 这题是给一个混合图(既有有向边又有无向边),让你判断是否有欧拉回路…… 我们知道如果一个[连通]图中每个节点都满足[入度=出度]那么就一定有欧拉回路…… 那么每条边都可 ...
- 【poj】1001
[题目] ExponentiationTime Limit: 500MS Memory Limit: 10000KTotal Submissions: 123707 Accepted: 30202De ...
随机推荐
- ThinkPHP/Common/extend.php
<?php // +---------------------------------------------------------------------- // | ThinkPHP [ ...
- VB 思维导图总结(二)
第六章.过程... 第七章.菜单工具栏... 第八章.文件系统处理.. 第九章.键盘和鼠标事件...
- Most People Aren’t.
Most people want to be fit, most people aren't. Most people want to build a successful business, mos ...
- Python标准库之os模块
1.删除和重命名文件 import os import string def replace(file, search_for, replace_with): # replace strings in ...
- 【BZOJ】【1662】/【POJ】【3252】 【USACO 2006 Nov】Round Number
数位DP 同上一题Windy数 预处理求个组合数 然后同样的方法,这次是记录一下0和1的个数然后搞搞 Orz cxlove /************************************* ...
- oracle 用户 多个表空间
首先,授权给指定用户. 一个用户的默认表空间只能有一个,但是你可以试下用下面的语句为其授权在别的表空间中创建对像: alter user username quota 0||unlimited on ...
- Relearning PHP (2) – php 的浮点数float
Relearning PHP (2) – php 的浮点数float 暂无评论 php有很多坑,但是并不妨碍他是最好的语言.其他语言对于浮点数处理同样有问题,这应该是个“共有坑”.不信可以用googl ...
- unity3d GameObject.Find 严格区分大小写的
GameObject.Find 查找 static function Find (name : string) : GameObject Description描述 Finds a game obje ...
- 深入浅出ES6(七):箭头函数 Arrow Functions
作者 Jason Orendorff github主页 https://github.com/jorendorff 箭头符号在JavaScript诞生时就已经存在,当初第一个JavaScript教 ...
- 深入理解JVM--类的执行机制
在完成将class文件信息加载到JVM并产生class对象之后,就可以执行Class对象的静态方法或者实例方法对对象进行调用了.JVM在源代码编译阶段将源代码编译为字节码文件,字节码是一种中间代码的方 ...