来学插头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. Vue购物车实例

    <div class="buyCarBox" id="buyCarBox" v-cloak> <div class="haveClo ...

  2. epoll的使用实例

    在网络编程中通常需要处理很多个连接,可以用select和poll来处理多个连接.但是select都受进程能打开的最大文件描述符个数的限制.并且select和poll效率会随着监听fd的数目增多而下降. ...

  3. React的JSX语法及组件

    最近一个同事很急没有做任何交接就请了陪产假,然后我来维护.说实在的我一开始是一脸懵逼的.因为MV*项目里用的最多的还是Vue:React听说也了解过,但毕竟不熟... 不过不管如何这也是工作:同事也恭 ...

  4. lesson - 6 Linux下磁盘管理

    1. 查看磁盘或者目录的容量df  查看磁盘各分区使用情况   不加参数以k为单位   df -i inode数,df -h  以G或者T或者M   df -m  以M单位显示  du 查看目录或者文 ...

  5. gitlab 远程 定时备份

    =============================================== 2017/11/1_第2次修改                       ccb_warlock 更新 ...

  6. Redis在APP中的应用

    前言 redis 是内存型数据库,读取data速度远快于mysql和sqlserver,如果将APP中列表信息或者一些常被访问的信息转存至内存上,然后APP通过redis读取内存上的数据,那么APP的 ...

  7. Shader 1:能接受阴影的透明shader

    第一次接触Shader,项目需要,直接说需求吧,需要一个透明并且能接受阴影的shader.unity系统自带的shader已经满足不了了.上一段代码吧 Shader "GreenArch/T ...

  8. 滚动条大于120px时,判断pc端的情况下,导航条固定定位

      //滚动条大于120px时,判断pc端的情况下,导航条固定定位 $(window).scroll(function(){ var viewWidth=$(document).width() var ...

  9. shell日志删除(超容量&自动)

    背景:避免双十一磁盘被打爆,本想通过crontab执行,但是删除需要密码,所以用作当机器磁盘高于摸个阈值,进行无关性日志强删 #!/bin/sh #use #sh clean.sh wmporder_ ...

  10. angularjs 怎么获取鼠标焦点 鼠标移入显示浮动的div提示框

    首先,我们要清楚几个基础的知识,angular的两个鼠标移入移出的指令------ng-mouseover(鼠标移入)ng-mouseleave(鼠标移出)--------还有就是window.eve ...