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的更多相关文章

  1. 【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, ...

  2. 【POJ】1067 取石子游戏(博弈论)

    Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后 ...

  3. 【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$都是偶数啦~ ...

  4. 【POJ】【2104】区间第K大

    可持久化线段树 可持久化线段树是一种神奇的数据结构,它跟我们原来常用的线段树不同,它每次更新是不更改原来数据的,而是新开节点,维护它的历史版本,实现“可持久化”.(当然视情况也会有需要修改的时候) 可 ...

  5. 【CodeForces】713 D. Animals and Puzzle 动态规划+二维ST表

    [题目]D. Animals and Puzzle [题意]给定n*m的01矩阵,Q次询问某个子矩阵内的最大正方形全1子矩阵边长.n,m<=1000,Q<=10^6. [算法]动态规划DP ...

  6. 【POJ】1222 EXTENDED LIGHTS OUT

    [算法]高斯消元 [题解] 高斯消元经典题型:异或方程组 poj 1222 高斯消元详解 异或相当于相加后mod2 异或方程组就是把加减消元全部改为异或. 异或性质:00 11为假,01 10为真.与 ...

  7. 【POJ】2892 Tunnel Warfare

    [算法]平衡树(treap) [题解]treap知识见数据结构 在POJ把语言从G++换成C++就过了……??? #include<cstdio> #include<algorith ...

  8. 【POJ】【1637】Sightseeing tour

    网络流/最大流 愚人节快乐XD 这题是给一个混合图(既有有向边又有无向边),让你判断是否有欧拉回路…… 我们知道如果一个[连通]图中每个节点都满足[入度=出度]那么就一定有欧拉回路…… 那么每条边都可 ...

  9. 【poj】1001

    [题目] ExponentiationTime Limit: 500MS Memory Limit: 10000KTotal Submissions: 123707 Accepted: 30202De ...

随机推荐

  1. .NET序员的成长之路

  2. c++各种排序

    1.插入排序 void InsertSort(int a[], int n) { int temp, i, j; ; i < n; i++) { ]) { temp = a[i]; ; j &g ...

  3. OC self super isa指针

    self指针: self是oc面向对象设计中的一个特殊指针,相当于java中的this,但是比this强大,this只能访问实例对象的相关方法和成员变量,或者说this只代表实例对象: self不仅可 ...

  4. Eclipse 3.7(代号Indigo) 中文字体太小解决办法(转)

    升级到3.7Eclipse最直观的反映就是,中文怎么那么小啊---- 相当不方便. 其实这是Eclipse的默认字体换了,以前的一直是Courier New,现在修改字体也找不到了,算了不找了. 这次 ...

  5. <a href='?out=login'>是什么意思

    <a href='?out=login'>退出</a>前面加上问号?就是GET方式传递out=login是要传递的数据点这个链接就可以执行 接下来通过$_GET["o ...

  6. 一点关于Ajax和一个等待图标的显示

    一点关于Ajax和一个等待图标的显示 1.首先Ajax是asynchronous Java-Script and XML的简写.翻译过来就是异步的JS和XML. 2它的优点就是能不更新页面的情况下,得 ...

  7. 利用JavaScript获取页面文档内容

    JavaScript的document对象包含了页面的实际内容,所以利用document对象可以获取页面内容,例如页面标题.各个表单值. <!DOCTYPE html> <html ...

  8. 《Dive into Python》Chapter 2 and Chapter 3 笔记

    Example 2.1. odbchelper.py def buildConnectionString(params): """Build a connection s ...

  9. Jquery.linq 使用示例

    http://linqjs.codeplex.com/ /*Linq JS*/ //range var aa = Enumerable.range(1, 10).toArray(); var kk = ...

  10. uva 11986

    假设有n只老鼠 每只老鼠有两种状态 死或活 则n只老鼠有 2^n方种状态 所以n只老鼠可以确定2^n只瓶子 #include <cstdio> #include <cstdlib&g ...