题目

给出 \(n*m\) 的方格,有些格子不能铺线,

其它格子必须铺,可以形成多个闭合回路。

问有多少种铺法? \(n,m\leq 12\)


分析

设 \(dp[n][m][S][0/1]\) 表示处理到 \((n,m)\),

目前插头的状态为 \(S\),并且左插头是否向右暴露,

插头的状态指的是轮廓线上的上插头是否向下暴露,这个分类讨论一下就可以了,

注意到右边界的位置左插头不能向右暴露,并且不能铺线的地方要继续更新方案


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
int n,m,al,a[12][12];
long long dp[4101][2],f[4101][2];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
signed main(){
for (rr int T=iut();T;--T){
memset(dp,0,sizeof(dp));
n=iut(),m=iut(),al=1<<m,dp[0][0]=1;
for (rr int i=0;i<n;++i)
for (rr int j=0;j<m;++j)
a[i][j]=iut();
for (rr int i=0;i<n;++i)
for (rr int j=0;j<m;++j){
if (a[i][j]){
for (rr int k=0;k<al;++k)
if ((k>>j)&1){
f[k][0]+=dp[k][0];//|
f[k^(1<<j)][1]+=dp[k][0];//L
f[k^(1<<j)][0]+=dp[k][1];//>
}else{
f[k][1]+=dp[k][1];//-
f[k|(1<<j)][0]+=dp[k][1];//7
f[k|(1<<j)][1]+=dp[k][0];//<
}
}else{
for (rr int k=0;k<al;++k)
if (!((k>>j)&1))
f[k][0]=dp[k][0];//不存在插头
}
if (j==m-1){
for (rr int k=0;k<al;++k)
f[k][1]=0;//不能有暴露的左插头
}
memcpy(dp,f,sizeof(dp));
memset(f,0,sizeof(f));
}
printf("%lld\n",dp[0][0]);
}
return 0;
}

简化

可以发现,dp数组能够被压成一维,记录 \(m+1\) 个插头,

轮廓线往右移动一格左插头也向右移动一个。

注意位于行末时需要移除右侧插头并补上左侧插头,即调整轮廓线的状态


代码(HDU 1693)

#include <cstdio>
#include <cctype>
using namespace std;
int T,two[14],n,m,al;
long long f[8192],dp[8192];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int main(){
T=iut(),two[0]=1;
for (int i=1;i<=13;++i) two[i]=two[i-1]<<1;
for (int _T=1;_T<=T;++_T){
n=iut(),m=iut(),al=two[m+1]-1;
for (int i=0;i<=al;++i) f[i]=0; f[0]=1;
for (int i=0;i<=al;++i) dp[i]=f[i];
for (int i=0;i<n;++i)
for (int j=0;j<m;++j){
int x=iut();
for (int S=0;S<=al;++S) f[S]=0;
for (int S=0;S<=al;++S)
if (dp[S]){
bool zuo=(S>>j)&1,upp=(S>>(j+1))&1;
if (x){
f[S^two[j]^two[j+1]]+=dp[S];//转弯
if (zuo!=upp) f[S]+=dp[S];//直行
}else if (!zuo&&!upp) f[S]+=dp[S];
}
for (int S=0;S<=al;++S)
if (j<m-1) dp[S]=f[S];
else dp[S]=(S&1)?0:f[S>>1];//行末最右侧的左插头不存在,插头整体往右移动一格,同时在左侧补上左插头
}
printf("Case %d: There are %lld ways to eat the trees.\n",_T,dp[0]);
}
return 0;
}

#插头dp#洛谷 5074 HDU 1693 Eat the Trees的更多相关文章

  1. hdu 1693 Eat the Trees——插头DP

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1693 第一道插头 DP ! 直接用二进制数表示状态即可. #include<cstdio> # ...

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

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

  3. HDU 1693 Eat the Trees(插头DP)

    题目链接 USACO 第6章,第一题是一个插头DP,无奈啊.从头看起,看了好久的陈丹琦的论文,表示木看懂... 大体知道思路之后,还是无法实现代码.. 此题是插头DP最最简单的一个,在一个n*m的棋盘 ...

  4. HDU - 1693 Eat the Trees(多回路插头DP)

    题目大意:要求你将全部非障碍格子都走一遍,形成回路(能够多回路),问有多少种方法 解题思路: 參考基于连通性状态压缩的动态规划问题 - 陈丹琦 下面为代码 #include<cstdio> ...

  5. HDU 1693 Eat the Trees(插头DP,入门题)

    Problem Description Most of us know that in the game called DotA(Defense of the Ancient), Pudge is a ...

  6. HDU 1693 Eat the Trees (插头DP)

    题意:给一个n*m的矩阵,为1时代表空格子,为0时代表障碍格子,问如果不经过障碍格子,可以画一至多个圆的话,有多少种方案?(n<12,m<12) 思路: 这题不需要用到最小表示法以及括号表 ...

  7. HDU 1693 Eat the Trees ——插头DP

    [题目分析] 吃树. 直接插头DP,算是一道真正的入门题目. 0/1表示有没有插头 [代码] #include <cstdio> #include <cstring> #inc ...

  8. hdu 1693 : Eat the Trees 【插头dp 入门】

    题目链接 题意: 给出一个n*m大小的01矩阵,在其中画线连成封闭图形,其中对每一个值为1的方格,线要恰好穿入穿出共两次,对每一个值为0的方格,所画线不能经过. 参考资料: <基于连通性状态压缩 ...

  9. HDU 1693 Eat the Trees

    第一道(可能也是最后一道)插头dp.... 总算是领略了它的魅力... #include<iostream> #include<cstdio> #include<cstr ...

  10. 【HDU】1693 Eat the Trees

    http://acm.hdu.edu.cn/showproblem.php?pid=1693 题意:n×m的棋盘求简单回路(可以多条)覆盖整个棋盘的方案,障碍格不许摆放.(n,m<=11) #i ...

随机推荐

  1. 硬件开发笔记(十六):RK3568底板电路mipi摄像头接口原理图分析、mipi摄像头详解

    前言   本篇继续分析底板原理图mipi电路原理图.mipi摄像头输入硬件接口详解.   RK3568芯片摄像头接口   查看RK3568的芯片手册,摄像头接口并不支持直接sensor模拟信号输入,只 ...

  2. 类型别名TypeAlias

    from collections.abc import Iterable from typing import TypeAlias FromTo = tuple[str, str] # 3.10之前 ...

  3. Kotlin 函数 与 lambda 表达式

    一.函数 代码块函数体: fun sum(x: Int, y: Int): Int { return x + y } 表达式函数体: fun sum(x: Int, y: Int) = x + y 使 ...

  4. 一次kafka消息丢失问题处理

    背景&现象 生产微服务架构环境,kafka消息消费服务架构如下: 当服务B接口出现宕机或者B接口调用超时,kafka消息消费端服务A出现异常,异常发生后未执行手动提交offset操作.待服务B ...

  5. 【Azure 应用服务】PHP项目部署到App Service for Linux环境中,如何修改上传文件大小的限制呢?

    问题描述 PHP项目部署到App Service for Linux环境中,如何修改上传文件大小的限制呢? 问题解答 经过查询Azure App Service官方文档,可能通过在项目根目录下添加.h ...

  6. FolkMQ 作个简单的消息中间件(最简单的那种), v1.3.1 发布

    功能简介 角色 功能 生产端(或发起端) 发布消息.定时消息(或叫延时).顺序消息.可过期消息.事务消息.发送消息(rpc)支持 Qos0.Qos1 消费端(或接收端) 订阅.取消订阅.消费-ACK( ...

  7. 四: Mysql用户管理

    # 用户与权限管理 MySQL用户可以分为普通用户和root用户, root用户是超级管理员,拥有所有权限,包括创建用户.删除用户和修改用户的密码等管理权限:普通用户只拥有被授予的各种权限. MySQ ...

  8. 从零开始搭建Springboot开发环境(Java8+Git+Maven+MySQL+Idea)之一步到位

    说明 所谓万事开头难,对于初学Java和Springboot框架的小伙伴往往会花不少时间在开发环境搭建上面.究其原因其实还是不熟悉,作为在IT界摸爬滚打数年的老司机,对于各种开发环境搭建已经了然于胸, ...

  9. dos-基础用法

    DOS(磁盘操作系统)是一个早期的基于命令行的操作系统,尽管现代操作系统已经发展为图形用户界面(GUI),但是了解和掌握一些基本的DOS命令仍然非常有用,尤其是在处理批处理脚本.网络管理或者在没有图形 ...

  10. 2023山东省“技能兴鲁”职业技能大赛-学生组初赛wp

    PWN pwn1 c++ pwn,cin 直接相当于 gets 了,程序有后门,保护基本没开,在 change 的最后一个输入点改掉返回地址为后门地址即可 from pwn import * cont ...