插头DP


本题为CDQ《基于连通性状态压缩的动态规划的……(我忘了)》里的例题!(嗯就是这样……)

先膜拜一下ccy大神……http://blog.sina.com.cn/s/blog_51cea4040100gmky.html

在这里将我当初看插头DP的一些不解之处写出来,给大家提供一些参考:

  以前我老是搞不懂“左/右插头”的区分……今天终于搞明白了:左插头是一个联通块与轮廓线的左边的交点,右插头是靠右的交点……这下那些分情况讨论的状态转移瞬间就明白了= =

  然后是状态表示……其实以前用状压都是一位表示一个状态,而插头DP由于用的是3(4)进制,所以是二进制下的两位来表示一个插头的状态(两位的话就可以表示0/1/2了,一位只能表示0/1)

  状态转移其实就是删掉/加上插头的操作……看了代码很好懂……sigh……当年是一看长代码就头晕,唉

  其实我们是在对每一个格子枚举可行状态的……要不然怎么叫统计方案数啊= =(这一点我一开始真的没想到……so sad……too naive)

  其实在看插头DP代码的过程中也顺便理解了Hash……原来hash向后排是这个意思,开个数组记录下每个hash值所对应的原值就好了,好像也没那么难的样子……为什么当初我NOIP的时候就没学会呢……

 //Ural 1519
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define CC(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*=sign;
}
const int N=1e7+;
typedef long long LL;
typedef unsigned long long u64;
/******************tamplate*********************/
const int sz=;
bool mp[][];
int n,m,nn,mm,k;
int tot[],bit[],hash[sz],state[][sz];
u64 dp[][sz],ans;
void init(){
CC(mp,);
CC(dp,);
tot[]=dp[][]=,ans=k=;
state[][]=;
char ch;
F(i,,n){
scanf("%c",&ch);
F(j,,m){
scanf("%c",&ch);
mp[i][j]=ch=='.';
if (mp[i][j]) nn=i,mm=j;
}
}
}
void hash_in(int s,u64 sum){
int p=s%sz;
while(hash[p]){
if (state[k][hash[p]]==s){
dp[k][hash[p]]+=sum;
return;
}
p++;
if (p==sz) p=;
}
hash[p]=++tot[k];
state[k][hash[p]]=s;
dp[k][hash[p]]=sum;
}
#define in hash_in(s,sum)
void work(){
F(i,,n){
F(j,,m){
k^=;
tot[k]=;
CC(hash,);
F(u,,tot[-k]){
int s=state[-k][u];
u64 sum=dp[-k][u];
int p=(s>>bit[j-])&,q=(s>>bit[j])&;
if (!mp[i][j]){ if(!p && !q) in; }
else{
if (!p && !q){
if (!mp[i][j+]||!mp[i+][j]) continue;
s=s^(<<bit[j-])^(<<bit[j]<<),in;
}else if(!p && q){
if (mp[i][j+]) in;
if (mp[i+][j]) s=s^q*(<<bit[j-])^q*(<<bit[j]),in;
}else if(p && !q){
if (mp[i+][j]) in;
if (mp[i][j+]) s=s^p*(<<bit[j-])^p*(<<bit[j]),in;
}else if(p+q==){
int nd=;
F(u,j+,m){
int w=(s>>bit[u])&;
if (w==) nd++;
if (w==) nd--;
if (!nd) {s-=(<<bit[u]); break;}//这两个地方不能将+/-改成^
//废话!因为这里是把右插头(2)改成左插头(1)了!用异或就把2改成3了……那算神马……
}
s=s^(<<bit[j])^(<<bit[j-]),in;
}else if(p+q==){
int nd=;
D(u,j-,){
int w=(s>>bit[u])&;
if (w==) nd++;
if (w==) nd--;
if (!nd) {s+=(<<bit[u]); break;}//这里是将左插头(1)改成右插头(2)
}
s=s^(<<bit[j]<<)^(<<bit[j-]<<),in;
}else if(p== && q==){
if (i==nn && j==mm) ans+=sum;
}else if(p== && q==) s=s^(<<bit[j-]<<)^(<<bit[j]),in;
}
}
}
F(j,,tot[k]) state[k][j]<<=;
}
printf("%llu\n",ans);
} int main(){
#ifndef ONLINE_JUDGE
freopen("1519.in","r",stdin);
freopen("1519.out","w",stdout);
#endif
F(i,,) bit[i]=i<<;
while(scanf("%d%d",&n,&m)!=EOF){
init();
work();
}
return ;
}

【Ural】【1519】Formula 1的更多相关文章

  1. 【Open Search产品评测】-- 淘点点:基于OpenSearch,轻松实现一整套O2O类搜索解决方案

     [Open Search产品评测]--  淘点点:基于OpenSearch,轻松实现一整套O2O类搜索解决方案   [使用背景] 我们淘点点团队应该可以算是内网首批使用opensearch来搭建应用 ...

  2. 【GO】【gdb】

    1 安装homebrew 参考 https://www.cnblogs.com/suren2017/p/9249803.html ([Ruby][环境搭建]macOS Sierra 10.12.6 + ...

  3. poj1952 BUY LOW, BUY LOWER【线性DP】【输出方案数】

    BUY LOW, BUY LOWER Time Limit: 1000MS   Memory Limit: 30000K Total Submissions:11148   Accepted: 392 ...

  4. Sigma Function (LightOJ - 1336)【简单数论】【算术基本定理】【思维】

    Sigma Function (LightOJ - 1336)[简单数论][算术基本定理][思维] 标签: 入门讲座题解 数论 题目描述 Sigma function is an interestin ...

  5. 【机器学习与R语言】12- 如何评估模型的性能?

    目录 1.评估分类方法的性能 1.1 混淆矩阵 1.2 其他评价指标 1)Kappa统计量 2)灵敏度与特异性 3)精确度与回溯精确度 4)F度量 1.3 性能权衡可视化(ROC曲线) 2.评估未来的 ...

  6. 【机器学习与R语言】8- 神经网络

    目录 1.理解神经网络 1)基本概念 2)激活函数 3)网络拓扑 4)训练算法 2.神经网络应用示例 1)收集数据 2)探索和准备数据 3)训练数据 4)评估模型 5)提高性能 1.理解神经网络 1) ...

  7. 【疯狂造轮子-iOS】JSON转Model系列之二

    [疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...

  8. 【疯狂造轮子-iOS】JSON转Model系列之一

    [疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...

  9. 【原创分享·支付宝支付】HBuilder打包APP调用支付宝客户端支付

    前言 最近有点空余时间,所以,就研究了一下APP支付.前面很早就搞完APP的微信支付了,但是由于时间上和应用上的情况,支付宝一直没空去研究.然后等我空了的时候,发现支付宝居然升级了支付逻辑,虽然目前还 ...

  10. 【AutoMapper官方文档】DTO与Domin Model相互转换(上)

    写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...

随机推荐

  1. PHP preg_replace() 正则替换所有符合条件的字符串示例

    PHP preg_replace() 正则替换,与Javascript 正则替换不同,PHP preg_replace() 默认就是替换所有符号匹配条件的元素.  需要用程序处理的数据并不总是预先以数 ...

  2. MySql中把一个表的数据插入到另一个表中的实现代码

    web开发中,我们经常需要将一个表的数据插入到另外一个表,有时还需要指定导入字段,设置只需要导入目标表中不存在的记录,虽然这些都可以在程序中拆分成简单sql来实现,但是用一个sql的话,会节省大量代码 ...

  3. char与 int 类型转化问题汇总

    1.char变为int时高位符号扩展问题 int main() { char a = 0x9a; int util; util = (int)a; if(util > 0) printf(&qu ...

  4. C语言中内存对齐方式

    一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...

  5. makefile复习时发现的编写makefile规则注意事项

    博客中关于makefile的博文数不胜数,比较经典的都很相似,下面这一片,很全面,只是很长,可以作为参考资料:http://blog.csdn.net/liang13664759/article/de ...

  6. 随机数范围扩展(如rand7()到rand10())(转)

    题目:已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10.分析:要保证rand10()在整数1-10的均匀分布,可以构造一个1-10*n的均 ...

  7. Android--获取短信的内容,截取短信

    1.首先我们要写一个广播接收器,当我们的手机收到短信时,系统会自动发送一个广播,我们只需要接收到这条广播就可以了 2.在广播里面,我们重写的onReceive()方法,通过里面的Intent写到的Bu ...

  8. WIN服务器出现 php-cgi.exe - FastCGI 进程意外退出

    既然是不能解析PHP,那就直接运行一下PHP,看会报什么错,再对症下药,于是,在命令提示符窗口进入php安装的根目录,然后运行php -v的命令,这时窗口弹出计算机丢失msvcr110.dll的错误, ...

  9. Windows Phone自定义控件 ProgressRing

    前言 Windows Phone为开发者提供了很多原生控件,但在很多场景下我们需要对默认的功能或样式做一定的修改才能满足我们的需求,自定义控件应运而生.本文通过以自定义控件进度环(ProgressRi ...

  10. python: 命令选项及归类

    usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ... Options and arguments (and corresp ...