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

然后分很多情况讨论:
(i,j)是障碍:那就只能什么都不放的转移,也就是只能从b1=0,b2=0转移到新轮廓线的b1=0,b2=0

if(!a[i][j]){if(!b1&&!b2)add(x,v);}

b1=0,b2=0:因为不能空,所以只能转移一个拐角

else if(!b1&&!b2){if(a[i+1][j]&&a[i][j+1])add(x+b[j-1]+2*b[j],v);}

b1=0或者b2=0:根据有无障碍判断能不能转移,如果(i,j+1),(i+1,j)都没有障碍的话就有两种转移,以b1=0,b2!=0为例:
一种是接上然后拐弯,这样转移后的轮廓线括号状态不变

另一种是接上直着走,转移后的轮廓线括号状态b1b2互换

b1!=0,b2=0同理

else if(!b1&&b2){if(a[i][j+1])add(x,v);if(a[i+1][j])add(x-b[j]*b2+b[j-1]*b2,v);}else if(b1&&!b2){if(a[i][j+1])add(x-b[j-1]*b1+b[j]*b1,v);if(a[i+1][j])add(x,v);}

b1=b2=1或2:这样这两条线会在(i,j)格子连起来,两队括号合成一对,以b1=b2=1为例:

else if(b1==1&&b2==1){for(int t=1,l=j+1;l<=m;l++){if((x>>(l*2))%4==1)t++;if((x>>(l*2))%4==2)t--;if(!t){add(x-b[j]-b[j-1]-b[l],v);break;}}}else if(b1==2&&b2==2){for(int t=1,l=j-2;l>=0;l--){if((x>>(l*2))%4==1)t--;if((x>>(l*2))%4==2)t++;if(!t){add(x+b[l]-2*b[j]-2*b[j-1],v);break;}}}

b1=2,b2=1:和上面差不多,就是把这两个括号合并就行了

else if(b1==2&&b2==1)add(x-2*b[j-1]-b[j],v);

b1=1,b2=2:这个只有到最后一个没障碍的点才能转移,因为这是把一条线连成一个回路的最后一步
其实不用转移,直接加进答案就行了

else if(i==tx&&j==ty)ans+=v;
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=15,mod=299989;
int n,m,la,nw,a[N][N],b[N],c[2],h[300005],tx,ty;
long long ans;
char s[N];
struct qwe
{int ne,to[2];long long va[2];
}e[300005];
void add(int x,long long v)
{int u=x%mod+1;for(int i=h[u];i;i=e[i].ne)if(e[i].to[nw]==x){e[i].va[nw]+=v;return;}e[++c[nw]].ne=h[u];e[c[nw]].to[nw]=x;e[c[nw]].va[nw]=v;h[u]=c[nw];
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",s+1);for(int j=1;j<=m;j++)if(s[j]=='.')a[i][j]=1,tx=i,ty=j;}b[0]=1;for(int i=1;i<=12;i++)b[i]=b[i-1]<<2;c[0]=1,e[1].va[0]=1,e[1].to[0]=0;for(int i=1;i<=n;i++){for(int j=1;j<=c[nw];j++)e[j].to[nw]<<=2;for(int j=1;j<=m;j++){la=nw,nw^=1;memset(h,0,sizeof(h));c[nw]=0;for(int k=1;k<=c[la];k++){int x=e[k].to[la],b1=(x>>(j*2-2))%4,b2=(x>>(j*2))%4;long long v=e[k].va[la];if(!a[i][j]){if(!b1&&!b2)add(x,v);}else if(!b1&&!b2){if(a[i+1][j]&&a[i][j+1])add(x+b[j-1]+2*b[j],v);}else if(!b1&&b2){if(a[i][j+1])add(x,v);if(a[i+1][j])add(x-b[j]*b2+b[j-1]*b2,v);}else if(b1&&!b2){if(a[i][j+1])add(x-b[j-1]*b1+b[j]*b1,v);if(a[i+1][j])add(x,v);}else if(b1==1&&b2==1){for(int t=1,l=j+1;l<=m;l++){if((x>>(l*2))%4==1)t++;if((x>>(l*2))%4==2)t--;if(!t){add(x-b[j]-b[j-1]-b[l],v);break;}}}else if(b1==2&&b2==2){for(int t=1,l=j-2;l>=0;l--){if((x>>(l*2))%4==1)t--;if((x>>(l*2))%4==2)t++;if(!t){add(x+b[l]-2*b[j]-2*b[j-1],v);break;}}}else if(b1==2&&b2==1)add(x-2*b[j-1]-b[j],v);else if(i==tx&&j==ty)ans+=v;}}}printf("%lld\n",ans);return 0;
}

转载于:https://www.cnblogs.com/lokiii/p/10117582.html

bzoj 1814: Ural 1519 Formula 1【插头dp】相关推荐

  1. bzoj1814 Ural 1519 Formula 1(插头dp模板题)

    1814: Ural 1519 Formula 1 Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 924  Solved: 351 [Submit][S ...

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

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

  3. BZOJ 1814 Ural 1519 Formula 1

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

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

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

  5. URAL1519 Formula 1 —— 插头DP

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

  6. 插头DP题目泛做(为了对应WYD的课件)

    题目1:BZOJ 1814 URAL 1519 Formula 1 题目大意:给定一个N*M的棋盘,上面有障碍格子.求一个经过所有非障碍格子形成的回路的数量. 插头DP入门题.记录连通分量. 1 #i ...

  7. POJ-1739 Tony's Tour 插头DP(单条路径)

    题目链接:http://poj.org/problem?id=1739 完全可以用Ural 1519 Formula 1 插头DP(单回路)的代码解决此题,只要把图修改一下: .... ....... ...

  8. [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识--这真的是一种很锻炼人的题型-- 每一道题的状态都不一样 ...

  9. HDU4084 插头dp

    题意:给定一个图,0是不能放的,然后现在有1X1和1X2方块,最后铺满该图,使得1X1使用次数在C到D之间,1X2次数随便,问有几种放法 思路:插头DP或轮廓线,多加一维DP讨论就可以 注意插头DP状 ...

最新文章

  1. FFmpeg4.1 视频解码,保存原始YUV数据
  2. java new thread参数_java线程池01-ThreadPoolExecutor构造方法参数的使用规则
  3. VScode中Python的交互式命令环境使用笔记
  4. 【渝粤教育】电大中专幼儿园课程论_1作业 题库
  5. 三菱数据移位指令_三菱plc移位指令用法详解
  6. 固定顶部(广告栏效果)
  7. kafka逻辑示意图以及命令
  8. 计算机系统结构简答题
  9. 在一个字符串中找到第一个只出现一次的字符。
  10. Java的static关键字使用
  11. 《整理的艺术》读后反思,“强迫症患者”的理论依据
  12. 学校机房计算机类型,学校计算机机房的管理和维护建议原稿(样例3)
  13. vue element-ui实现input输入框金额数字添加千分位
  14. 链路追踪译文学习记录(Dapper!!!非原创!!!学习记录)
  15. 17个品牌,113款5G手机,5G离我们越来越近。
  16. 记事正文 - QQ邮箱
  17. 复合型网络拓扑结构图_网络拓扑结构大全和图片(星型、总线型、环型、树型、分布式、网状拓扑结构)....
  18. 机器人与视觉,基于TCP(工具坐标)偏移
  19. 英文版windows 中文软件乱码的解决方案:设置Locale
  20. 模拟角频率和数字角频率

热门文章

  1. Linux安装wine以及运行Windows程序
  2. Java学习之什么是泛型的擦除
  3. 算法 图1 列出连通集
  4. LTE网络PUCCH功控计算
  5. Paramiko和MySQL相关-day10
  6. dataframe python,使用pandas dataframe python创建实时更新图
  7. windows系统通过CMD将文件copy到远程电脑
  8. JQuery源码分析之—— 整体构架
  9. 一个技术创业者的自白:你为什么想创业?
  10. 芝诺数解|【二】风禾尽起,且住为佳——重庆租房