来学插头DP了= =

  GDKOI前觉得不会考数位DP,GDOI前觉得插头DP用不上。。

  结果令人伤感>_<

  这题并不用增加状态。。

  只要在形成环的时候,让形成环的位置在最后一个必走点之后,并且此时只有一个联通分量。

  因为必走点处肯定有插头。。所以只有一个联通分量就意味着所有必走点都连在一起了。

  选择经过的点就在转移的时候多一种方法。。。

学的是最小表示法。。又长又慢TAT。。跳错坑了= =

 #include<cstdio>
#include<iostream>
#include<cstring>
#define ull unsigned long long
using namespace std;
const int modd=,maxzt=;
struct zs{
struct hash{
ull too;int pre;
}e[maxzt];int tot,last[modd];
ull f[maxzt],zt[maxzt]; inline int get(ull v){
int i,x=v%modd;
for(i=last[x];i&&e[i].too!=v;i=e[i].pre);
if(i&&e[i].too==v)return i;
e[++tot].too=v,e[tot].pre=last[x],last[x]=tot;
zt[tot]=v;f[tot]=;
return tot;
}
}hm[];
int i,j,k,n,m,tx,ty;
int can[][];
ull ans;
char s[];
int v[]; inline void clr(bool now){
memset(hm[now].last,,modd<<),
hm[now].tot=;
} bool u[];int id[],mp[];
inline ull encode(){
memset(u,,);
ull x=;int tt=;
for(int i=;i<=m;mp[i]=id[mp[i]],x=x<<|mp[i],i++)
if(mp[i]&&!u[mp[i]])u[mp[i]]=,id[mp[i]]=++tt;
return x;
}
inline void decode(ull x){
for(int i=m;i>=;i--)mp[i]=x&,x>>=;
}
inline void shift(){
for(int i=m;i;i--)mp[i]=mp[i-];
mp[]=;
} inline void dp_blank(int x,int y,bool pre){
int i,left,up,j;bool now=pre^;ull zt,f;
clr(now);
for(i=;i<=hm[pre].tot;i++){
zt=hm[pre].zt[i],f=hm[pre].f[i],
decode(zt);
left=mp[y-],up=mp[y];
if(!left&&!up){
if(can[x+][y]&&can[x][y+]){
mp[y-]=mp[y]=;
if(y==m)shift();
hm[now].f[ hm[now].get(encode()) ]+=f;
}
if(can[x][y]==){
mp[y-]=mp[y]=;
if(y==m)shift();
hm[now].f[ hm[now].get(encode()) ]+=f;
}
}
if((!left)^(!up)){
j=left|up;
if(can[x+][y]){
mp[y-]=j,mp[y]=;
if(y==m)shift();
hm[now].f[ hm[now].get(encode()) ]+=f;
}
if(can[x][y+]){
mp[y-]=,mp[y]=j;
if(y==m)shift();
hm[now].f[ hm[now].get(encode()) ]+=f;
}
}
if(left&&up){
if(left==up)
if(x>tx||(x==tx&&y>=ty)){
mp[y-]=mp[y]=;
if(encode()==)ans+=f;
}else;
else{
mp[y-]=mp[y]=;
for(j=;j<=m;j++)if(mp[j]==up)mp[j]=left;
if(y==m)shift();
hm[now].f[ hm[now].get(encode()) ]+=f;
}
}
}
}
inline void dp_bar(int x,int y,bool pre){
int i,left,up;bool now=pre^;ull f,zt;
clr(now);
for(i=;i<=hm[pre].tot;i++){
zt=hm[pre].zt[i],f=hm[pre].f[i];
decode(zt);
left=mp[y-],up=mp[y];
if(!left&&!up){
if(y==m)shift();
hm[now].f[ hm[now].get(encode()) ]+=f;
}
}
} int main(){
int TT;
scanf("%d",&TT);v['X']=,v['O']=,v['*']=;
for(int TTT=;TTT<=TT;TTT++){
scanf("%d%d",&n,&m);
memset(can,,sizeof(can));
for(i=;i<=n;i++)
for(scanf("%s",s+),j=;j<=m;j++){
can[i][j]=v[s[j]];
if(s[j]=='O')tx=i,ty=j;
} for(i=n,j=;i;i--){
for(j=m;j;j--)if(can[i][j]==)break;
if(j>)break;
}
tx=i,ty=j; bool now=,pre=;ans=;
clr(),hm[pre].f[ hm[pre].get() ]=;
for(i=;i<=n;i++)for(j=;j<=m;j++,swap(now,pre))
if(can[i][j])dp_blank(i,j,pre);else dp_bar(i,j,pre);
printf("Case %d: %I64u\n",TTT,ans);
}
return ;
}

[FZU1977] Pandora adventure的更多相关文章

  1. FZU1977 Pandora adventure —— 插头DP

    题目链接:https://vjudge.net/problem/FZU-1977  Problem 1977 Pandora adventure Accept: 597    Submit: 2199 ...

  2. 【FZU】1977 Pandora adventure

    http://acm.fzu.edu.cn/problem.php?pid=1977 题意:n×m的网格,有3种格子,'O'必须经过.'*'可以选择经过.'X'不能经过.现在要求路径经过所有'O'且是 ...

  3. FZU 1977 Pandora adventure (DP)

    题意:给定一个图,X表示不能走,O表示必须要走,*表示可走可不走,问你多少种走的法,使得形成一个回路. 析: 代码如下: #pragma comment(linker, "/STACK:10 ...

  4. FZU 1977 Pandora adventure (插头DP,常规)

    题意:有一个n*m矩阵,其中有些格子必走,有些格子不可走,其他格子是可走也可不走,问有多少条哈密顿回路? 思路: 本来是一道很简单的题,代码写多了连白痴bug都查不出了,竟然用i>=ex& ...

  5. 插头DP专题

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

  6. DP:0

    小故事: A * "1+1+1+1+1+1+1+1 =?" * A : "上面等式的值是多少" B : *计算* "8!" A *在上面等式 ...

  7. 插头dp练习

    最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...

  8. HDU 3377 Plan (插头DP,变形)

    题意:有一个n*m的矩阵,每个格子中有一个值(可能负值),要从左上角走到右下角,求路径的最大花费. 思路: 除了起点和终点外,其他的点可以走,也可以不走. (2)我用的是括号表示法,所以起始状态为') ...

  9. Java基础-接口看下图实现如下接口和类,并完成Adventure中的主方法

    package hanqi; public interface CanSwim { void swim(); } package hanqi; public interface CanFly { pu ...

随机推荐

  1. Simple Games Using SpriteKit

    p.p1 { margin: 0.0px 0.0px 12.0px 0.0px; line-height: 14.0px; font: 12.0px Times; color: #000000 } s ...

  2. C:函数:功能:实现字符数组中所有字母的倒序存放并输出

    前两天小测碰到一道题,建立一个函数,功能:实现字符数组中所有字母的倒序存放并输出,一开始觉得简单跟数字数组差不多,运行一下发现很多格式错误,这些是不必要的错误,现在就来说下,先说一下代码思路:定义一个 ...

  3. php按照中文首字母排序

    1> 网络上很多php的工具类可以将汉字转为拼音: 2> 将拼音进行排序即可 另一种则是类似mysql转码方式: 1 foreach ($array as $key=>$value) ...

  4. jQuery 文档操作方法

    jQuery 文档操作方法 这些方法对于 XML 文档和 HTML 文档均是适用的,除了:html(). 方法 描述 addClass() 向匹配的元素添加指定的类名. after() 在匹配的元素之 ...

  5. php 理解

    <?php class t { var $num; var $dynamic_function; public function dynamic_function() { $func = $th ...

  6. JDK动态代理[4]----ProxyGenerator生成代理类的字节码文件解析

    通过前面几篇的分析,我们知道代理类是通过Proxy类的ProxyClassFactory工厂生成的,这个工厂类会去调用ProxyGenerator类的generateProxyClass()方法来生成 ...

  7. NoFragment重大bug

    在activity中切换fragment,有以下几点问题需要注意: 例如做一个类似于这样的tab切换fragment的,有以下几点问题 1.切换fragment后,前几个fragment能透视,解决方 ...

  8. robotframework学习笔记(七)------筛选执行用例

    第一种:手动勾选用例 可勾选用户,然后点击运行,这样就只运行到勾选的用例.如果不勾选的点击运行就会运行所有用例. 第二种 菜单中去筛选 可在菜单中去筛选勾用例,然后点击运行 Select All Te ...

  9. 微信小程序入门

    自己看了一下微信小程序 其实  还是很简单的    官方有现成的api 跟 组件给你用   我的感觉就像是一个  前端框架  类似于  ionic 这种   感觉比ionic还要简单 里面的wxml  ...

  10. gitlab markdown支持页面内跳转

    markdown语法: [to_be_link](#id_name) 标题: ## 2.aaa <a name="id_name"></a> 参考: htt ...