这种动归有很多名字,插头DP是最常见的

还有基于连通性的动态规划

轮廓线动态规划等等

超小数据范围,网格图,连通性

可能算是状态压缩DP的一种变式

以前我了解的状压DP用于NP难题的小数据范围求解

这里说一下哈密顿回路的概念:

哈密顿回路:
、指一个对图的每个顶点都只穿越一次的回路。也可以 定义为n+1个相邻顶点v0, v1, … ,vn, v0的一个序列,其中序列的第一个顶点和最后一个顶点是相同的,而其他n-1个顶点是互不相同的。
、当这个图是加权图时,求该图的最短哈密顿回路,就是传说中的旅行商问题(TSP)。

然后是一道插头DP的入门题

一个网格图中有若干障碍格子,求其他格子的哈密尔顿回路总数

 #include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int LIM=,Has=;
int n,m,e1,e2,las,now,tt;LL ans;
int mp[][],bin[],tot[];LL js[][LIM];
int h[],a[][LIM],ne[LIM];
//tot:状态总数,js:该状态的方案总数,a:各种状态
void ins(int zt,LL num) {//卓越的哈希技术
int tmp=zt%Has+;
for(int i=h[tmp];i;i=ne[i])
if(a[now][i]==zt) {js[now][i]+=num;return;}
ne[++tot[now]]=h[tmp],h[tmp]=tot[now];
a[now][tot[now]]=zt,js[now][tot[now]]=num;
}
void work() {
tot[now]=,js[now][]=,a[now][]=;
for(int i=;i<=n;++i) {
for(int j=;j<=tot[now];++j) a[now][j]<<=;//切换行了
for(int j=;j<=m;++j) {
las=now,now^=;
memset(h,,sizeof(h)),tot[now]=;
for(int k=;k<=tot[las];++k) {
int zt=a[las][k],b1=(zt>>(j*-))%,b2=(zt>>(j*))%;//提取关键格子上的两段轮廓线状态
LL num=js[las][k];
if(!mp[i][j]) {if(!b1&&!b2) ins(zt,num);}
else if(!b1&&!b2)
{if(mp[i+][j]&&mp[i][j+]) ins(zt+bin[j-]+*bin[j],num);}
else if(!b1&&b2) {
if(mp[i][j+]) ins(zt,num);
if(mp[i+][j]) ins(zt-bin[j]*b2+bin[j-]*b2,num);
}
else if(b1&&!b2) {
if(mp[i][j+]) ins(zt-bin[j-]*b1+bin[j]*b1,num);
if(mp[i+][j]) ins(zt,num);
}
else if(b1==&&b2==) {
int kl=;
for(int t=j+;t<=m;++t) {
if((zt>>(t*))%==) ++kl;
if((zt>>(t*))%==) --kl;
if(!kl) {ins(zt-bin[j]-bin[j-]-bin[t],num);break;}
}
}
else if(b1==&&b2==) {
int kl=;
for(int t=j-;t>=;--t) {
if((zt>>(t*))%==) --kl;
if((zt>>(t*))%==) ++kl;
if(!kl) {ins(zt+bin[t]-*bin[j]-*bin[j-],num);break;}
}
}
else if(b1==&&b2==) ins(zt-*bin[j-]-bin[j],num);
else if(i==e1&&j==e2) ans+=num;
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
for(int j=;j<=m;++j) {
char ch=getchar();
while(ch!='*'&&ch!='.') ch=getchar();
if(ch=='.') mp[i][j]=,e1=i,e2=j;
}
bin[]=;for(int i=;i<=;++i) bin[i]=bin[i-]<<;
work(),printf("%lld\n",ans);
return ;
}

然后是HDU1693

给一个n*m的地图,有些格子是不可到达的,要把所有可到达的格子的树都吃完,并且要走回路,求方案数

允许有多个回路,找一条或多条回路,吃完所有的树

 #include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n,m,T,kas,bin[],mp[][];LL f[][][(<<)];
int main()
{
scanf("%d",&T);
bin[]=;for(int i=;i<=;++i) bin[i]=bin[i-]<<;
while(T--) {
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
for(int j=;j<=m;++j) scanf("%d",&mp[i][j]);
memset(f,,sizeof(f));
f[][m][]=;int lim=bin[m+]-;
for(int i=;i<=n;++i) {
for(int zt=;zt<=lim;++zt) f[i][][zt<<]=f[i-][m][zt];
for(int j=;j<=m;++j)
for(int zt=;zt<=lim;++zt) {
int b1=zt&bin[j-],b2=zt&bin[j];LL num=f[i][j-][zt];
if(!mp[i][j]) {if(!b1&&!b2) f[i][j][zt]+=num;}
else if(!b1&&!b2)
{if(mp[i][j+]&&mp[i+][j])f[i][j][zt+bin[j-]+bin[j]]+=num;}
else if(!b1&&b2) {
if(mp[i][j+]) f[i][j][zt]+=num;
if(mp[i+][j]) f[i][j][zt-bin[j]+bin[j-]]+=num;
}
else if(b1&&!b2) {
if(mp[i][j+]) f[i][j][zt-bin[j-]+bin[j]]+=num;
if(mp[i+][j]) f[i][j][zt]+=num;
}
else f[i][j][zt-bin[j-]-bin[j]]+=num;
}
}
printf("Case %d: There are %lld ways to eat the trees.\n",++kas,f[n][m][]);
}
return ;
}

动态规划:插头DP的更多相关文章

  1. 51Nod1518 稳定多米诺覆盖 动态规划 插头dp 容斥原理

    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1518.html 题目传送门 - 51Nod1518 题意 51Nod真是个好OJ ,题意概括的真好, ...

  2. bzoj1814: Ural 1519 Formula 1 动态规划 插头dp

    http://acm.timus.ru/problem.aspx?space=1&num=1519 题目描述 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数. ...

  3. 动态规划之插头DP入门

    基于联通性的状态压缩动态规划是一类非常典型的状态压缩动态规划问题,由于其压缩的本质并不像是普通的状态压缩动态规划那样用0或者1来表示未使用.使用两种状态,而是使用数字来表示类似插头的状态,因此.它又被 ...

  4. 插头DP(基于连通性状态压缩的动态规划问题)(让你从入门到绝望)

    今天,我,Monkey king 又为大家带来大(ju)佬(ruo)的算法啦!--插头DP 例题(菜OJ上的网址:http://caioj.cn/problem.php?id=1489): 那么,这道 ...

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

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

  6. Luogu P3886 [JLOI2009]神秘的生物 最小表示法,轮廓线DP,插头DP,动态规划

    亲手写掉的第一道最小表示法!哈哈哈太开心啦~ 不同于以往的几个插头\(dp\),这个题目的轮廓线是周围的一圈\(n\)个格子.而其所谓"插头"也变成了相邻格子的所属连通分量编号,并 ...

  7. 插头DP专题

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

  8. 动态规划——数位dp

    通过先前在<动态规划——背包问题>中关于动态规划的初探,我们其实可以看到,动态规划其实不是像凸包.扩展欧几里得等是具体的算法,而是一种在解决问题中决策的思想.在不同的题目中,我们都需要根据 ...

  9. 初探 插头DP

    因为这题,气得我火冒三丈! 这数据是不是有问题啊!我用cin代替scanf后居然就AC了(本来一直卡在Test 18)!导致我调(对)试(排)了一个小时!! UPD:后来细细想想,会不会是因为scan ...

随机推荐

  1. OpenNF tutorial复现

    这篇博客记录了自己实现OpenNF官网上tutorial的过程和遇见的问题,如果有不对的地方还请批评指正! tutorial链接 实验内容 这个实验展示了如何迅速且安全地把一个TCP流从一个NF实例迁 ...

  2. Java 线程安全问题

    线程安全问题产生原因: 1.多个线程操作共享的数据: 2.操作共享数据的线程代码有多条.   当一个线程正在执行操作共享数据的多条代码过程中,其它线程也参与了运算, 就会导致线程安全问题的发生. cl ...

  3. iOS-封装UIPickerView

    创建类WJPickerView继承与UIView ProvinceModel是省市的model,包含属性 @property (nonatomic, strong) NSString *provinc ...

  4. 安装libvirt管理套件(C/S架构模式,用户管理kvm虚拟机)

    # 1:安装程序包 yum install -y libvirt virt-manager virt-viewer virt-install qemu-kvm   # 2:启动libvirtd守护进程 ...

  5. 敏捷冲刺DAY8

    一. 每日会议 1. 照片 2. 昨日完成工作 第一次阶段测试. 3. 今日完成工作 对前七次敏捷冲刺的工作进行完善. 4. 工作中遇到的困难 浏览器兼容性问题.页面响应性能问题.内存溢出问题-- 二 ...

  6. Communications link failure--分析之(JDBC的多种超时情况)

    本文是针对特定的情景下的特定错误,不是所有Communications link failure错误都是这个引起的,重要的区分特点是:程序是不是在卡主后两个小时(服务器的设置)后程序才感知到,才抛出了 ...

  7. 【数据库】SQL两表之间:根据一个表的字段更新另一个表的字段

    1. 写法轻松,更新效率高:update table1 set field1=table2.field1,field2=table2.field2from table2where table1.id= ...

  8. poj2299——Ultra-QuickSort

    Description In this problem, you have to analyze a particular sorting algorithm. The algorithm proce ...

  9. The meterprter basic commonds

    Using Meterpeter commands Since the Meterpreter provides awhole new environment, we will cover some ...

  10. js new date()说明

    javaScript UTC() 方法: UTC() 方法可根据世界时返回 1970 年 1 月 1 日 到指定日期的毫秒数. 要创建一个一个日期对象,可以使用以下的方式: var now=new D ...