【DFS】【打表】Lattice Animals
[ZOJ2669]Lattice Animals
Time Limit: 5 Seconds Memory Limit: 32768 KB
Lattice animal is a set of connected sites on a lattice. Lattice animals on a square lattice are especially popular subject of study and are also known as polyminoes. Polymino is usually represented as a set of sidewise connected squares. Polymino with n squares is called n-polymino.
In this problem you are to find a number of distinct free n-polyminoes that fit into rectangle w * h. Free polyminoes can be rotated and flipped over, so that their rotations and mirror images are considered to be the same.
For example, there are 5 different pentaminoes (5-polyminoes) that fit into 2 * 4 rectangle and 3 different octominoes (8-polyminoes) that fit into 3 * 3 rectangle.
Input
There are several test cases in the input. Each case consists of a single line with 3 integer numbers n, w, and h (n ≤ 10, 1 ≤ w, h ≤ n).
Output
Write to the output file a single integer number --- the number of distinct free n-polyminoes that fit into rectangle w * h.
Sample Input
5 1 4
5 2 4
5 3 4
5 5 5
8 3 3
Sample Output
0
5
11
12
3
Source: Northeastern Europe 2004
这是NEERC2004的题目,好像有两个人A……
ZOJ的测评机跑的貌似比较快,交其它OJ全都是TLE,网上部分标程也是。我叫UVA上RE不知道为何……
题目大意就是生成N连块,N<=10,然后有一堆询问,每次询问N连块中,有W*H的棋盘可以放下多少个N连块。
先将N连块求出来,然后再将每个N连块的贡献记入答案。时间限制虽然是5秒,但是应该要掌握预处理在2秒以内才可以(反正2.1秒的我T了)
ZOJ上690MS,orz 0ms秒过的dalao……
众多标程都是与刘汝佳一样用的Set,跑起来貌似能比一样思想的程序快1秒(亲测)
试题分析:大暴力:直接枚举下一个块可以放在哪里,拓展即可。
很容易想到一个优化:用N-1连块的答案来更新N连块的答案(显而易见不会漏掉答案)
当然,加上旋转翻转等一类Set的简易操作,貌似就可以了。
但我并没有写Set(不会很无奈啊,从来不用),然后就引来了众多莫名其妙的优化。
Part1(优化3秒左右):Hash
Hash优化是最先想到的一类优化,两个块一样必定Hash值相等,因此搞了两个Hash,其实一个Hash足矣。实测时间差不多。
Part2(Hash优化后优化200ms左右):W,H
注意到从N-1连块到N连块的长度或者高度最多其中一项+1.
这时我们就可以只翻转+旋转W,H这一块,其余并不用翻转,Hash、判断相等也只用这一块就好了。
现在就自然而然就多了一个剪枝:当两个块的W,H其一不等时,这两个块一定不相等。
Part3(上两项优化完后优化1s左右):Del
Del是去0操作,旨在去掉上面和左边的0,保证图形在10*10的棋盘的左上角。
发现Del多了,删去后就优化1s左右。
还有一些优化想出来了但没有用,可能不会优化太多:
将每个N连块每行每列的有几个块都求出来,然后比完Hash与W,H后比这两个信息是否一样,不一样则退出。
但这并不能完全确定一个联通块,比如:
110 101
111 111
001 010
这样列是:2 2 2 2 2 2
行是:2 3 1 2 3 1
一开始就是写完了这个发现不行,然后删了想了想又写了一天上面的东西。。。
个人认为题还是挺不错的,值得一做,但要做好心理准备……
代码:
- #include<iostream>
- #include<cstring>
- #include<vector>
- #include<queue>
- #include<algorithm>
- using namespace std;
- #define LL long long
- inline int read(){
- int x=0,f=1;char c=getchar();
- for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
- for(;isdigit(c);c=getchar()) x=x*10+c-'0';
- return x*f;
- }
- const int INF=9999999;
- const int MAXN=100000;
- const int T=10;
- int N,M,K;
- int Maxd;
- bool vis[21][21];
- bool vist[21][21];
- int W1,H1;
- int dis[5][2]={{0,1},{1,0},{0,-1},{-1,0}};
- bool txt[21][21];
- struct data{
- int w,h;
- bool mp[21][21];
- int dit[21];long long dit2[21];
- long long Hash1,Hash2;
- };
- vector<data> vec[21];
- void del0(){
- int move=INF;
- for(int i=0;i<T;i++){
- int cnt=-1;
- while(!txt[i][cnt]) cnt++;
- move=min(cnt-1,move);
- }
- if(move>=0){
- for(int i=0;i<T;i++){
- for(int j=move+1;j<T;j++){
- txt[i][j-move-1]=txt[i][j];
- txt[i][j]=0;
- }
- }
- }
- move=INF;
- for(int j=0;j<T;j++){
- int cnt=-1;
- while(!txt[cnt][j]) cnt++;
- move=min(cnt-1,move);
- }
- if(move>=0){
- for(int i=move+1;i<T;i++){
- for(int j=0;j<T;j++){
- txt[i-move-1][j]=txt[i][j];
- txt[i][j]=0;
- }
- }
- }
- return ;
- }
- bool vis2[21][21];
- int ans[21][21][21];
- int W,H;
- int dig[21];long long dig2[21];
- void rota(){
- memset(vis2,0,sizeof(vis));
- for(int i=0;i<H1;i++)
- for(int j=0;j<W1;j++) vis2[i][j]=txt[i][j];
- memset(txt,0,sizeof(txt));
- for(int i=0;i<H1;i++){
- for(int j=0;j<W1;j++)
- txt[j][i]=vis2[i][W1-j-1];
- }
- swap(W1,H1);
- return ;
- }
- long long Has;
- bool judge(){
- int t=vec[Maxd].size();
- if(!t) return true;
- for(int i=0;i<5;i++){
- if(i) rota();
- Has=0;
- for(int a=0;a<H1;a++){
- long long cnt=0;
- for(int b=0;b<W1;b++){
- if(txt[a][b]) cnt+=((1<<b)*a);
- }
- Has+=cnt;
- dig[a]=cnt;
- }
- long long Has2=0;
- for(int a=0;a<H1;a++){
- long long cnt=0;
- for(int b=0;b<W1;b++){
- if(txt[a][b]) cnt+=(1<<(a*b)+a*b)%999997;
- }
- dig2[a]=cnt;
- Has2+=cnt;
- Has2%=999999997;
- }
- for(int j=0;j<t;j++){
- if(Has!=vec[Maxd][j].Hash1) continue;
- if(Has2!=vec[Maxd][j].Hash2) continue;
- if(W1!=vec[Maxd][j].w||H1!=vec[Maxd][j].h) continue;
- bool flag=true;
- for(int a=0;a<H1;a++)
- if(dig[a]!=vec[Maxd][j].dit[a]) {
- flag=false;break;
- }
- if(!flag) continue;
- for(int a=0;a<H1;a++)
- if(dig2[a]!=vec[Maxd][j].dit2[a]) {
- flag=false;break;
- }
- if(!flag) continue;
- for(int a=0;a<H1;a++){
- for(int b=0;b<W1;b++){
- if(vec[Maxd][j].mp[a][b]!=txt[a][b]){
- flag=false;
- break;
- }
- }
- if(!flag) break;
- }
- if(flag) return false;
- }
- }
- return true;
- }
- void pushin(){
- data tk;
- long long Has2=0;
- for(int i=0;i<T;i++)
- for(int j=0;j<T;j++)
- tk.mp[i][j]=txt[i][j];
- for(int a=0;a<H1;a++){
- long long cnt=0;
- for(int b=0;b<W1;b++){
- if(txt[a][b]) cnt+=((1<<b)*a);
- }
- tk.dit[a]=cnt;
- Has2+=cnt;
- }
- tk.Hash1=Has2;
- Has2=0;
- for(int a=0;a<H1;a++){
- long long cnt=0;
- for(int b=0;b<W1;b++){
- if(txt[a][b]) cnt+=(1<<(a*b)+a*b)%999997;
- }
- tk.dit2[a]=cnt;
- Has2+=cnt;
- Has2%=999999997;
- }
- tk.Hash2=Has2;
- tk.w=W1;
- tk.h=H1;
- vec[Maxd].push_back(tk);
- return ;
- }
- bool ti[21][21];
- void GA(int d){
- for(int a=1;a<=H+1;a++)
- for(int b=1;b<=W+1;b++){
- if(!vis[a][b]) continue;
- for(int k=0;k<4;k++){
- int xx=dis[k][0]+a;
- int yy=dis[k][1]+b;
- if(xx>=T||yy>=T) continue;
- if(ti[xx][yy]) continue;
- if(vis[xx][yy]) continue;
- ti[xx][yy]=true;
- vis[xx][yy]=1;
- for(int i=0;i<T;i++)
- for(int j=0;j<T;j++) txt[i][j]=vis[i][j];
- del0();
- int h=0;
- for(int i=0;i<T;i++){
- int p=T-1;
- while(!txt[i][p]) p--;
- h=max(h,p+1);
- }
- W1=h;
- int w=0;
- for(int j=0;j<T;j++){
- int p=T-1;
- while(!txt[p][j]) p--;
- w=max(w,p+1);
- }
- H1=w;
- vis[xx][yy]=0;
- if(!judge()) continue;
- rota();
- for(int i=0;i<H1/2;i++)
- for(int j=0;j<W1;j++)
- swap(txt[i][j],txt[H1-i-1][j]);
- if(!judge()) continue;
- pushin();
- }
- }
- return ;
- }
- void pre(){
- txt[0][0]=1;
- Maxd=1;
- pushin();
- txt[0][0]=0;
- for(Maxd=2;Maxd<=T;Maxd++) {
- for(int i=0;i<vec[Maxd-1].size();i++){
- W=vec[Maxd-1][i].w;H=vec[Maxd-1][i].h;
- memset(vis,0,sizeof(vis));
- for(int j=0;j<T;j++)
- for(int k=0;k<T;k++)
- vis[j][k]=vec[Maxd-1][i].mp[j][k];
- for(int k=T-1;k>0;k--)
- for(int j=0;j<T;j++)
- vis[k][j]=vis[k-1][j],vis[k-1][j]=0;
- for(int k=0;k<T;k++)
- for(int j=T-1;j>0;j--)
- vis[k][j]=vis[k][j-1],vis[k][j-1]=0;
- memset(ti,0,sizeof(ti));
- GA(1);
- }
- for(int i=0;i<vec[Maxd].size();i++){
- for(int j=1;j<=10;j++)
- for(int k=1;k<=10;k++){
- if((vec[Maxd][i].w<=k&&vec[Maxd][i].h<=j)||(vec[Maxd][i].w<=j&&vec[Maxd][i].h<=k)) ans[Maxd][j][k]++;
- }
- }
- }
- }
- int main(){
- pre();
- while(scanf("%d%d%d",&N,&M,&K)!=EOF){
- if(N==1) puts("1");
- else printf("%d\n",ans[N][M][K]);
- }
- return 0;
- }
【DFS】【打表】Lattice Animals的更多相关文章
- DFS+打表
N皇后问题 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status ...
- HDU 2586 How far away(dfs+邻接表)
How far away [题目链接]How far away [题目类型]dfs+邻接表 &题意: 题目大意:一个村子里有n个房子,这n个房子用n-1条路连接起来,接下了有m次询问,每次询问 ...
- HDU 2563 统计问题 (DFS + 打表)
统计问题 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- UVA-1602 Lattice Animals 搜索问题(打表+set)
题目链接 https://vjudge.net/problem/UVA-1602 紫书的一道例题,跟之前的很多题目有很多不同. 本题不像是一般的dfs或bfs这样的搜索套路,而是另一种枚举思路. 题意 ...
- ACM: HDU 2563 统计问题-DFS+打表
HDU 2563 统计问题 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u HDU 2 ...
- codeforces 285 D. Permutation Sum 状压 dfs打表
题意: 如果有2个排列a,b,定义序列c为: c[i] = (a[i] + b[i] - 2) % n + 1 但是,明显c不一定是一个排列 现在,给出排列的长度n (1 <= n <= ...
- hdu 2510 符号三角形 (DFS+打表)
符号三角形 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- hdu2510-符号三角形(dfs+打表)
n只有24 可以写个暴力搜索,然后打表,不然这个很难通过剪枝直接优化到1s以内. #include<bits/stdc++.h> #define inf 0x3f3f3f3f ; usin ...
- hdu 1848 sg——dfs&&打表双实现
Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
随机推荐
- 2009 Round2 A Crazy Rows (模拟)
Problem You are given an N x N matrix with 0 and 1 values. You can swap any two adjacent rows of the ...
- C++获取系统时间的方法
//首先是了解这个结构体,_SYSTEMTIME ,然后通过系统函数GetLocalTime往这个结构体的变量中写入当前系统时间typedef struct _SYSTEMTIME { WORD wY ...
- Angular2.0 基础: User Input
1.Angular 2.0 中的变量 对输入值的获取,我们可以通过$event 来获取,也可以通过变量来获取. template: ` <input (keyup)="onKey($e ...
- 【Python学习笔记】有关包的基本知识
python的包(package)是一个有层次的文件目录结构.它定义了一个由模块和子包组成的Python应用程序执行环境. AAA/ __init__.py bbb.py CCC/ __init__. ...
- 自动化测试===Macaca环境搭建,自我总结
安装jdk 安装安卓sdk(打开sdk的时候出现问题linux===启动sdk manager下载配置sdk的时候报错的解决办法) 安装gradle,配置环境变量(MACACA===gradle下载和 ...
- selenium.webdriver.common.keys 模块中常用的变量
表11-5 selenium.webdriver.common.keys 模块中常用的变量属性 含义Keys.DOWN, Keys.UP, Keys.LEFT,Keys.RIGHT 键盘箭头键Keys ...
- python按比例随机切分数据
在机器学习或者深度学习中,我们常常碰到一个问题是数据集的切分.比如在一个比赛中,举办方给我们的只是一个带标注的训练集和不带标注的测试集.其中训练集是用于训练,而测试集用于已训练模型上跑出一个结果,然后 ...
- canvas制作柱形图/折线图/饼状图,Konva写动态饼状图
制作饼状图 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- MYSQL5.5源码安装 linux下
/* 首先安装必要的库 */ yum -y install gcc* ###### 安装 MYSQL ###### 首先安装camke 一.支持YUM,则 yum install -y cmake 二 ...
- DRF的@action装饰器
# 转自:http://www.cnblogs.com/zhzhlong/p/9325180.html 视图集中附加action的声明 from rest_framework.decorators i ...