1814: Ural 1519 Formula 1

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 924  Solved: 351
[Submit][Status][Discuss]

Description

一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数

Input

The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop) means a cell, where a segment of the race circuit should be built, and character "*" (asterisk) - a cell, where a gopher hole is located.

Output

You should output the desired number of ways. It is guaranteed, that it does not exceed 2^63-1.

Sample Input

4 4
**..
....
....
....

Sample Output

2
分析:今天把插头dp学了一下,没想到dp还能写这么长......细节什么的也很多,在这里当一个模板吧.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;
typedef long long ll;const int maxn = 30010;
const int pow[13] = {0,2,4,6,8,10,12,14,16,18,20,22,24};
int n,m,now,pre,tx,ty;
char map[20][20];struct node
{int head[maxn],nextt[maxn],tot;ll sum[maxn],sta[maxn];void clear(){memset(head,-1,sizeof(head));tot = 0;}void push(ll x,ll v){ll hashh = x % maxn;for (int i = head[hashh]; i >= 0; i = nextt[i]){if (sta[i] == x){sum[i] += v;return;}}sta[tot] = x;sum[tot] = v;nextt[tot] = head[hashh];head[hashh] = tot++;}
} f[2];int turnleft(ll x,int k)
{return x << pow[k];
}int get(ll x,int k)
{return (x >> pow[k]) & 3;
}ll del(ll x,int i,int j)
{return x & (~(3 << pow[i])) & (~(3 << pow[j]));
}int findr(ll x,int pos)
{int cnt = 1;for (int i = pos + 1; i <= m; i++){int k = get(x,i);if (k == 1)cnt++;else if (k == 2)cnt--;if (!cnt)return i;}
}int findl(ll x,int pos)
{int cnt = 1;for (int i = pos - 1; i >= 0; i--){int k = get(x,i);if (k == 2)cnt++;else if (k == 1)cnt--;if (!cnt)return i;}
}void solve2(int x,int y,int k)
{int p = get(f[pre].sta[k],y - 1);   //右插头int q = get(f[pre].sta[k],y);   //下插头ll staa = del(f[pre].sta[k],y - 1,y);   //将这两个插头删掉以后的状态ll v = f[pre].sum[k];if (!p && !q)  //新建一个连通分量
    {if (map[x][y] == '*'){f[now].push(staa,v);return;}if (x < n && y < n && map[x + 1][y] == '.' && map[x][y + 1] == '.')f[now].push(staa | turnleft(1,y - 1) | turnleft(2,y),v);}else if (!p || !q)  //保持原来的连通分量
    {int temp = p + q;if (x < n && map[x + 1][y] == '.')f[now].push(staa | turnleft(temp,y - 1),v);if (y < m && map[x][y + 1] == '.')f[now].push(staa | turnleft(temp,y),v);}else if (p == 1 && q == 1)    //连接两个联通分量f[now].push(staa ^ turnleft(3,findr(staa,y)),v);  //这里的异或实际上就是把1变成2,2变成1else if (p == 2 && q == 2)f[now].push(staa ^ turnleft(3,findl(staa,y - 1)),v);else if (p == 2 && q == 1)f[now].push(staa,v);else if (x == tx && y == ty)f[now].push(staa,v);
}ll solve()
{f[0].clear();f[0].push(0,1);now = 0,pre = 1;  //滚动数组for (int i = 1; i <= n; i++){pre = now;now ^= 1;f[now].clear();for (int k = 0; k < f[pre].tot; k++)f[now].push(turnleft(f[pre].sta[k],1),f[pre].sum[k]);   //左移一位,因为轮廓线下来的时候会少一个插头for (int j = 1; j <= m; j++){pre = now;now ^= 1;f[now].clear();for (int k = 0; k < f[pre].tot; k++)solve2(i,j,k);  //处理第k个状态
        }}for (int i = 0; i < f[now].tot; i++)if (f[now].sta[i] == 0)  //没有插头了.return f[now].sum[i];return 0;
}int main()
{scanf("%d%d",&n,&m);for(int i = 1; i <= n; i++)scanf("%s",map[i] + 1);for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)if (map[i][j] == '.')tx = i,ty = j; //找右下角的非障碍点if (!tx)puts("0");elseprintf("%lld\n",solve());return 0;
}

转载于:https://www.cnblogs.com/zbtrs/p/8457162.html

bzoj1814 Ural 1519 Formula 1(插头dp模板题)相关推荐

  1. 【BZOJ1814】Ural 1519 Formula 1 插头DP

    [BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...

  2. Ural 1519. Formula 1 优美的插头DP

    今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的, ...

  3. URAL1519 Formula 1 —— 插头DP

    题目链接:https://vjudge.net/problem/URAL-1519 1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB ...

  4. BZOJ 1814 Ural 1519 Formula 1

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1814 题解 插头dp,枚举边界线的插头,分类讨论转移点上插头和左插头的情况,来转移这个点 ...

  5. 【每日DP】day2、P1879 [USACO06NOV]Corn Fields G玉米地(状压DP模板题)难度⭐⭐⭐★

    昨天的每日DP我还在写01背包,今天就到状压DP了,真刺激. P1879 [USACO06NOV]Corn Fields G 题目链接 输入 2 3 1 1 1 0 1 0 输出 9 一道简单的状压D ...

  6. 动态规划DP模板题汇总

    前言 动态规划的实现逻辑是画图分前后状态,二维数组肯定能解决,但是为了降低复杂度,又会转换成一维数组,线性DP,或者存在反向DP,能节省很多思考的情况.并且保证状态的更新不会影响之前状态的计算结果. ...

  7. 不要62(HDU-2089)(数位DP模板题)

    杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍 ...

  8. ACW各种dp模板题 day29

    背包的就不贴上来了 感觉没啥好说的 AcWing 898. 数字三角形 线性dp 第一题 应该都是一眼秒吧 感觉自己第一遍学的时候是真的菜 呃呃 我们注意边界情况就可以了 状态转移没啥好说的 下一道 ...

  9. bzoj 1814: Ural 1519 Formula 1【插头dp】

    设f[i][j][s]为轮廓线推到格子(i,j),状态为s的方案数 括号表示一段线的左端和右端,表示成左括号和右括号,状压的时候用1和2表示,0表示已经闭合 下面的蓝线是黄色格子的轮廓线,dp转移要把 ...

最新文章

  1. 解决Mask RCNN训练时GPU内存溢出问题
  2. SAP MM供应商主数据表
  3. 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 使用反射获取方法创建本应用的 dexElements | 各版本创建 dex 数组源码对比 )
  4. 逆向学习技术!拆解驱动器,学习布局走线技术
  5. hdu 5792 World is Exploding 树状数组
  6. python语言的重要性_【一点资讯】这个可能打败Python的编程语言,正在征服科学界 www.yidianzixun.com...
  7. PopupWindow的一些使用总结
  8. 浮点数不能全等比较吗php,汇编语言FCOM指令:比较浮点数值
  9. 数据 正则化 python_Python数据科学:正则化方法
  10. flv 视频 文件 下载
  11. 物联网嵌入式高级C语言流行框架、学习路线图
  12. 硬盘三大种类( SSD ; HHD ; HDD )
  13. 如何使投资收益最大化?
  14. c++7-1 无符号整数的内部结构 - C/C++ 指针及引用
  15. Jetpack Compose入门详解(实时更新)
  16. 交换机SVI配置的作用 思科/华为 网络工程
  17. 面试题、排序、socket总结
  18. FlatBuffers vs Protocol Buffers
  19. 使用shell脚本探测网段内在使用的IPv4地址
  20. SOLIDWORKS怎么把STEP曲面转换成实体

热门文章

  1. Hibernate之mappedBy
  2. 能够附加图片的标签控件iOS项目源码
  3. 解决VirtualBox 上的XP 关机时重启 , 启动时蓝屏 ,点击电源选项蓝屏
  4. Lean Startup
  5. 《LeetCode力扣练习》第136题 只出现一次的数字 Java
  6. Mybatis-Plus一个新的报错:数据库表名与SQL的关键字冲突!!!
  7. Linux系统下配置Java环境
  8. c#_Dictionary集合
  9. animate用法 js原生_用 原生Javascript 创建带动画的固顶导航菜单
  10. linux 代码获取当前路径,【linux】shell代码,获取当前路径,创建文件夹