正题

题目链接:https://www.luogu.com.cn/problem/P3170


题目大意

给出\(n*m\)的网格上有一些障碍,要求用三个\(L\)形(高宽随意,不能退化成线段/点)覆盖格子且\(L\)形之间不能重叠。

求覆盖方案(每个\(L\)形相同)

\(2\leq n,m\leq 30\)


解题思路

一道比模板要简单的插头\(dp\)?(当然我依旧不会)

先是考虑插头的状态,每个\(L\)形的话,一个还没有涂完的\(L\)形可能是右插头或者下插头,因为只有三个所以最多只会有\(3\)个下插头,这样的状态数是\(C_m^3\)的,在\(5000\)以内。

把这些状态压缩起来,然后设\(f_{x,y,s,k,0/1}\)表示现在\(dp\)到格子\((x,y)\),目前下插头状态为\(s\),已经插入了\(k\)个\(L\)形(作为下插头),目前有没有右插头。

转移的话就很简单了,如果下一个格子有障碍那它上面就不能有插头,如果这个格子上面有插头就分为结束这个下插头变为一个右插头或者不结束。

如果这个格子有右插头那么就不能有上插头。

没有这些限制就能够开一个下插头。

需要注意到行尾的时候可能会还有右插头,在最右边加一列障碍就好了。

时间复杂度是\(O(nmC_{m}^3)\)的


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=32,M=5100;
ll n,m,cnt,f[N][M][4][2];
ll id[N][N][N],pi[M],pj[M],pk[M];
bool v[N][N];char s[N];
void init(){
for(ll i=0;i<=m;i++)
for(ll j=i?(i+1):0;j<=m;j++)
for(ll k=j?(j+1):0;k<=m;k++){
id[i][j][k]=++cnt;
pi[cnt]=i;pj[cnt]=j;pk[cnt]=k;
}
ll p[3];
for(ll i=0;i<=m;i++)
for(ll j=0;j<=m;j++)
for(ll k=0;k<=m;k++){
p[0]=i;p[1]=j;p[2]=k;sort(p,p+3);
id[i][j][k]=id[p[0]][p[1]][p[2]];
}
return;
}
signed main()
{
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++){
scanf("%s",s+1);
for(ll j=1;j<=m;j++)
if(s[j]=='#')v[i][j]=1;
}
m++;
for(ll i=1;i<=n;i++)v[i][m]=1;
ll g=0;f[0][1][0][0]=1;init();
for(ll p=1;p<=n*m;p++){
ll x=(p-1)/m+1,y=(p-1)%m+1;
g^=1;memset(f[g],0,sizeof(f[g]));
for(ll s=1;s<=cnt;s++){
ll a=pi[s],b=pj[s],c=pk[s];
for(ll k=0;k<=3;k++){
if(f[!g][s][k][0]){
if(!v[x][y]){
f[g][s][k][0]+=f[!g][s][k][0];
if(y==a)f[g][id[0][b][c]][k][1]+=f[!g][s][k][0];
else if(y==b)f[g][id[a][0][c]][k][1]+=f[!g][s][k][0];
else if(y==c)f[g][id[a][b][0]][k][1]+=f[!g][s][k][0];
else if(k<3) f[g][id[y][b][c]][k+1][0]+=f[!g][s][k][0];
}
else if(y!=a&&y!=b&&y!=c)
f[g][s][k][0]+=f[!g][s][k][0];
}
if(f[!g][s][k][1]&&!v[x][y]&&y!=a&&y!=b&&y!=c){
f[g][s][k][1]+=f[!g][s][k][1];
f[g][s][k][0]+=f[!g][s][k][1];
}
}
}
}
printf("%lld\n",f[g][1][3][0]);
return 0;
}

P3170-[CQOI2015]标识设计【插头dp】的更多相关文章

  1. Luogu P3170 [CQOI2015]标识设计 状态压缩,轮廓线,插头DP,动态规划

    看到题目显然是插头\(dp\),但是\(n\)和\(m\)的范围似乎不是很小.我们先不考虑复杂度设一下状态试试: 一共有三个连通分量,我们按照\(1,2,3\)的顺序来表示一下.轮廓线上\(0\)代表 ...

  2. [专题总结]初探插头dp

    彻彻底底写到自闭的一个专题. 就是大型分类讨论,压行+宏定义很有优势. 常用滚动数组+哈希表+位运算.当然还有轮廓线. Formula 1: 经过所有格子的哈密顿回路数. 每个非障碍点必须有且仅有2个 ...

  3. 插头Dp总结

    T1 HDU1693:Eat the Trees 题目大意:给出n*m的方格,有些格子不能铺线,其它格子必须铺,可以形成多个闭合回路.问有多少种铺法? 插头Dp板子题,题目要求可以是多个回路, 只需要 ...

  4. 「总结」插头$dp$

    集中做完了插头$dp$ 写一下题解. 一开始学的时候还是挺蒙的. 不过后来站在轮廓线$dp$的角度上来看就简单多了. 其实就是一种联通性$dp$,只不过情况比较多而已了. 本来转移方式有两种.逐行和逐 ...

  5. 插头dp

    插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...

  6. HDU 4113 Construct the Great Wall(插头dp)

    好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...

  7. HDU 4949 Light(插头dp、位运算)

    比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...

  8. 插头DP专题

    建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...

  9. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

随机推荐

  1. Javascript - Vue - webpack中的axios

    导入axios import Vue from "vue";import axios from "axios";import { get } from &quo ...

  2. mybaits源码分析(一)

    一.源码下载 1.手动编译源码 为了方便在看源码的过程中能够方便的添加注释,可以从官网下载源码编译生成对应的Jar包,然后上传到本地maven仓库,再引用这个Jar. 首先需要编译打包parent项目 ...

  3. go进阶--测试

    目录 1.单元测试 1.1项目结构 1.2 源代码文件 1.3 单元测试 1.4 执行测试 1.5 单元测试总结 2.性能测试 2.1 项目结构 2.2 源码文件 2.3 测试文件 2.4 执行测试 ...

  4. jekins

    上面是:maven配置 git安装: 容器安装: 容器配置与发布: 添加安全认证(如果tomcat没有设置密码这里也不需要设置:) 访问尝试:本地测试前置practice_war的影响 Jekins实 ...

  5. NVidia Jetson Ubuntu 18.04 安装ROS过程中运行sudo rosdep init指令出错

    参考:https://www.cnblogs.com/xuhaoforwards/p/9399744.html 安装ROS过程中运行sudo rosdep init后,出现如下错误LOG: ERROR ...

  6. JavaSE-Java基础面试题

    重载与重写的区别 重载:本类中,方法名相同,参数列表不同,(参数类型.参数顺序.参数个数),返回值类型可以不同,访问修饰符可不同 重写:子类中,方法名相同,参数不能改,返回值类型一致或其子类,访问权限 ...

  7. LeetCode通关:连刷三十九道二叉树,刷疯了!

    分门别类刷算法,坚持,进步! 刷题路线参考:https://github.com/youngyangyang04/leetcode-master 大家好,我是拿输出博客来督促自己刷题的老三,这一节我们 ...

  8. 假期作业03:使用IDE开发你的Java程序

    假期作业03:使用IDE开发你的Java程序 一.使用Eclipse创建一个Java项目HelloWorldPrj,编写一个Java程序并运行. 首先要下载eclipse. (注意这里要选一个中国的, ...

  9. leetcode 括号

    1. 括号(0809) 设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合. 说明:解集不能包含重复的子集. 例如,给出 n = 3,生成结果为: [ "((()))" ...

  10. ☕【Java技术指南】「难点-核心-遗漏」Java线程状态流转及生命周期的技术指南(知识点串烧)!

    前提介绍 本章主要介绍相关线程声明周期的转换机制以及声明周期的流转关系以及相关AQS的实现和相关的基本原理,配合这相关官方文档的中英文互译的介绍. 线程状态流转及生命周期 当线程被创建并启动以后,它既 ...