题目链接
题意

给出n*m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路。问有多少种铺法?

思路

比赛时基本做不出来,就学个新算法玩玩。

学习链接

代码对于我这个不会hash_table 的不太友好,先自己封装了一个用着舒服的hash_table,当然也可以直接用STL里的 unordered_map,初学算法我认为直接使用后者更好,循序渐进。

插头dp简单的说还是轮廓线的状压dp?,多考虑了一种连通性问题。
用括号表示法表示轮廓线后,然后考虑状态转移。
枚举每点,考虑左边的朝右插头 r,上边朝下插头 d,左插头1表示,右插头2表示

  • if 当前点是障碍
  • else if (!r && !d)
  • else if (r && !d)
  • else if (!r && d)
  • else if (r == 1 && d == 1)
  • else if (r == 2 && d == 2)
  • else if (r == 1 && d == 2)
  • else if (r == 2 && d == 1)

所有的情况就这么多,然后每点考虑插头形状转移即可

一个坑点 | ^ 运算符优先级不同,不是从左到右运算,然后找了半天bug,还是用 + - 比较稳。

代码

STL unordered_map
代码
991ms
吸氧后 228ms

#include <bits/stdc++.h>
using namespace std;#define ll long longunordered_map<ll,ll> dp[3];
// chatou 0 null, 1 right, 2 down
ll n, m, endx, endy, a[15][15], bit[15];
#define prel (1ll<<bit[j-1])
#define prer (1ll<<bit[j])void solve() {ll cur = 0, ans = 0;dp[cur].clear();dp[0][0] = 1;for(ll i = 1; i <= n; ++i) {dp[2].clear();for(auto j : dp[cur]) dp[2][j.first<<2] = j.second;dp[cur] = dp[2];for(ll j = 1; j <= m; ++j) {cur ^= 1;dp[cur].clear();for(auto k : dp[cur^1]) {ll sta = k.first;ll w = k.second;ll d = (sta>>bit[j])&3ll;ll r = (sta>>bit[j-1])&3ll;
//                    printf("%lld %lld - %lld %lld\n",i,j,sta,w);
//                    printf("%lld = %lld\n\n",r,d);if(!a[i][j]) {if(!r && !d) dp[cur][sta] += w;}else if(!r && !d) {if(a[i+1][j] && a[i][j+1]) dp[cur][sta + prel + (2*prer)] += w;}else if(r && !d) {if(a[i+1][j]) dp[cur][sta] += w;if(a[i][j+1]) dp[cur][sta - (r*prel) + (r*prer)] += w;}else if(!r && d) {if(a[i+1][j]) dp[cur][sta + (d*prel) - (d*prer)] += w;if(a[i][j+1]) dp[cur][sta] += w;}else if(r == 1 && d == 1) {ll cnt = 1;for(ll p = j+1; p <= m; ++p) {if(((sta>>bit[p])&3ll) == 1) ++cnt;if(((sta>>bit[p])&3ll) == 2) --cnt;if(!cnt) {dp[cur][(sta - (r*prel) - (d*prer)) - (1<<bit[p])] += w;break;}}}else if(r == 2 && d == 2) {ll cnt = 1;for(ll p = j-2; p >= 0; --p) {if(((sta>>bit[p])&3ll) == 1) --cnt;if(((sta>>bit[p])&3ll) == 2) ++cnt;if(!cnt) {dp[cur][(sta - (r*prel) - (d*prer)) + (1<<bit[p])] += w;break;}}}else if(r == 2 && d == 1) {dp[cur][sta - (r*prel) - (d*prer)] += w;}else if(r == 1 && d == 2) { // okif(i == endx && j == endy) ans += w;}}}}printf("%lld\n",ans);
}int main() {scanf("%lld%lld",&n,&m);for(ll i = 1; i <= n; ++i) {char s[15];scanf("%s",s+1);for(ll j = 1; j <= m; ++j) {if(s[j] == '.') {a[i][j] = 1;endx = i;endy = j;}}}for(ll i = 1; i <= 13; ++i) bit[i] = i<<1;solve();return 0;
}

手写hash_table
代码
577ms
吸氧后 562ms

#include <bits/stdc++.h>
using namespace std;#define ll long longstruct hash_table {ll hash_mod = 590027;ll state[600000], ans[600000], up;ll tot, first[600000], nxt[600000], w[600000];void init() {memset(first, 0, sizeof(first));tot = 0;up = 0;}ll ins(ll sta, ll val) {ll key = sta%hash_mod;for(ll i = first[key]; i; i = nxt[i]) {if(state[w[i]] == sta) return ans[w[i]] += val;}state[++up] = sta;ans[up] = val;nxt[++tot] = first[key];w[tot] = up;first[key] = tot;return val;}
}dp[2];/*hash_table*/
// chatou 0 null, 1 right, 2 down
ll n, m, endx, endy, a[15][15], bit[15];
#define prel (1ll<<bit[j-1])
#define prer (1ll<<bit[j])void solve() {ll cur = 0, ans = 0;dp[cur].init();dp[0].ins(0,1);for(ll i = 1; i <= n; ++i) {for(ll j = 1; j <= dp[cur].up; ++j) dp[cur].state[j] <<= 2;for(ll j = 1; j <= m; ++j) {cur ^= 1;dp[cur].init();for(ll k = 1; k <= dp[cur^1].up; ++k) {ll sta = dp[cur^1].state[k];ll w = dp[cur^1].ans[k];ll d = (sta>>bit[j])&3ll;ll r = (sta>>bit[j-1])&3ll;
//                    printf("%lld %lld - %lld %lld\n",i,j,sta,w);
//                    printf("%lld = %lld\n\n",r,d);if(!a[i][j]) {if(!r && !d) dp[cur].ins(sta,w);}else if(!r && !d) {if(a[i+1][j] && a[i][j+1]) dp[cur].ins(sta + prel + (2*prer),w);}else if(r && !d) {if(a[i+1][j]) dp[cur].ins(sta,w);if(a[i][j+1]) dp[cur].ins(sta - (r*prel) + (r*prer),w);}else if(!r && d) {if(a[i+1][j]) dp[cur].ins(sta + (d*prel) - (d*prer),w);if(a[i][j+1]) dp[cur].ins(sta,w);}else if(r == 1 && d == 1) {ll cnt = 1;for(ll p = j+1; p <= m; ++p) {if(((sta>>bit[p])&3ll) == 1) ++cnt;if(((sta>>bit[p])&3ll) == 2) --cnt;if(!cnt) {dp[cur].ins((sta - (r*prel) - (d*prer)) - (1<<bit[p]),w);break;}}}else if(r == 2 && d == 2) {ll cnt = 1;for(ll p = j-2; p >= 0; --p) {if(((sta>>bit[p])&3ll) == 1) --cnt;if(((sta>>bit[p])&3ll) == 2) ++cnt;if(!cnt) {dp[cur].ins((sta - (r*prel) - (d*prer)) + (1<<bit[p]),w);break;}}}else if(r == 2 && d == 1) {dp[cur].ins(sta - (r*prel) - (d*prer),w);}else if(r == 1 && d == 2) { // okif(i == endx && j == endy) ans += w;}}}}printf("%lld\n",ans);
}int main() {scanf("%lld%lld",&n,&m);for(ll i = 1; i <= n; ++i) {char s[15];scanf("%s",s+1);for(ll j = 1; j <= m; ++j) {if(s[j] == '.') {a[i][j] = 1;endx = i;endy = j;}}}for(ll i = 1; i <= 13; ++i) bit[i] = i<<1;solve();return 0;
}

洛谷 P5056 【模板】插头dp相关推荐

  1. 洛谷--橙色百道DP总结

    最近刷完了洛谷橙色DP大约一百道,算是发现了一些套路,就部分题目做一些总结. 大概分为三类 第一类,九大背包及其衍生 第二类,经典DP模型,如LCS,LIS等 第三类,实际问题背景的普通,环形,树上D ...

  2. Educational Codeforces Round 81 (Rated for Div. 2) F.Good Contest \ 洛谷 划艇 组合 计数dp

    cf传送门 P3643 [APIO2016]划艇 文章目录 题意: 思路: 题意: aia_iai​在[li,ri][l_i,r_i][li​,ri​]等概率随机选一个数,求aaa数组不增的概率. 思 ...

  3. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 "低价购买"这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:"低价购买:再低价购买".每次你购买一支股 ...

  4. 洛谷P1244 青蛙过河 DP/思路

    又是一道奇奇怪怪的DP(其实是思路题). 原文戳>>https://www.luogu.org/problem/show?pid=1244<< 这题的意思给的挺模糊,需要一定的 ...

  5. 洛谷 P2657 (数位DP)

    ### 洛谷 P2657 题目链接 ### 题目大意:给你一个数的范围 [A,B] ,问你这段区间内,有几个数满足如下条件: 1.两个相邻数位上的数的差值至少为 2 . 2.不包含前导零. 很简单的数 ...

  6. 洛谷 Golden Sword(dp,优先队列优化【含板子】)|| 补充练习:洛谷 跳房子

    题目链接: 「SWTR-03」Golden Sword - 洛谷 思路: 设表示放第i个原料,锅里共有 j 个时的耐久度之和. 容易知道dp方程为,其中 这样就可以写出暴力dp的代码如下:(需要枚举i ...

  7. 专题·树链剖分【including 洛谷·【模板】树链剖分

    初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...

  8. 洛谷·【模板】点分树 | 震波【including 点分树

    初见安-这里是传送门:洛谷P6329 [模板]点分树 | 震波 一.点分树 其实你会点分治的话,点分树就是把点分治时的重心提出来重新连城一棵树. 比如当前点是u,求出子树v的重心root后将root与 ...

  9. 【洛谷P4719】动态DP【LCT】【矩阵】

    之前的后缀平衡树其实没完,只是过于鬼畜就弃了 传送门 题意:带修改点权的最大独立集 N≤1e5N \leq 1e5N≤1e5 一个没啥用的模板,不过适合练习LCT 先写出方程 f(u,0)=∑v∈so ...

  10. 强连通分量:洛谷P3387 模板:缩点

    传送门 顾名思义,模板awa #include <cstdio> #include <cstring> #include <cmath> #include < ...

最新文章

  1. BPDU tunnel技术简介
  2. Swift可选绑定、断言
  3. JavaScript学习备忘
  4. GitHub 2017 年度报告,最受欢迎的编程语言是?
  5. C#基础系列 - 抽象类及其方法的学习
  6. 并发事务正确性的准则 可串行化_从0到1理解数据库事务(上):并发问题与隔离级别...
  7. 【转】C++/CLI入门系列 第二篇:封装C++ dll库,提供接口给C#调用
  8. oracle 分页_80分页查询,不止写法
  9. mysql建用户之后取消drop库权限
  10. Windows 下 PHP 开发环境配置系列四 - IIS+php+mysql
  11. android sqlite 数据库中使用的类型
  12. mysql_fetch_row()获取显示数据
  13. 【论文翻译笔记】A Systematic Evaluation of StaticAPI-Misuse Detectors
  14. mysql 数据库索引命名规范_MYSQL数据库命名及设计规范
  15. ofd文件转化成pdf的免费方法
  16. 单词语音音标正则式查询分析JavaScript应用
  17. SQL编程和高级查询
  18. Mac电脑的文件快捷访问工具:Default Folder X 5
  19. 如何绕过强制门户——克隆 MAC 地址
  20. 银联支付、支付宝支付和微信支付有什么优势?

热门文章

  1. 线路板板SMT贴片中二极管正负极区分方法
  2. java里的文件显示繁体_java保存繁体网页打开后出现乱码
  3. myBatis约束文档
  4. python因子分析 ic值 函数_spss问卷调查因子分析定义变量及内容输入
  5. 郝斌c语言视频笔记,郝斌老师C语言专题笔记
  6. C语言编写小程序——万年历
  7. 易语言逐条读access数据_易语言数据库教程之ACCESS数据库全操作
  8. 雅虎相册批量下载v3.0 公布!支持相册主人登录 欢迎大家试用
  9. 稀疏编码的经典解法——ISTA算法的推导
  10. 企业人事系统 java_java企业人事管理系统