zoukankan      html  css  js  c++  java
  • 插头dp 模版

    有障碍,

    ***。。

    。。。。

    求回路数量

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int LIM=300005,Has=299989;
    int n,m,e1,e2,las,now,tt;LL ans;
    int mp[15][15],bin[15],tot[2];LL js[2][LIM];
    int h[300005],a[2][LIM],ne[LIM];
    //tot:状态总数,js:该状态的方案总数,a:各种状态
    void ins(int zt,LL num) {//卓越的哈希技术
        int tmp=zt%Has+1;
        for(int i=h[tmp];i;i=ne[i])//h相当于一个头
            if(a[now][i]==zt)
            {
                js[now][i]+=num;//找到了对应状态
                return;
            }
        ne[++tot[now]]=h[tmp];
        h[tmp]=tot[now];//头是新的计数器,指向以前的h
        a[now][tot[now]]=zt;//把当前计数器e的状态和数量修改
        js[now][tot[now]]=num;
    }
    
    void work() {
        tot[now]=1,js[now][1]=1,a[now][1]=0;
        for(int i=1;i<=n;++i) {
            
            for(int j=1;j<=tot[now];++j)
                a[now][j]<<=2;//切换行了
            
            for(int j=1;j<=m;++j) {
                las=now,now^=1;
                memset(h,0,sizeof(h)),tot[now]=0;
                
                for(int k=1;k<=tot[las];++k) {
                    int zt=a[las][k],b1=(zt>>(j*2-2))%4,b2=(zt>>(j*2))%4;//提取关键格子上的两段轮廓线状态
                    
                    LL num=js[las][k];
                    
                    if(!mp[i][j])
                    {
                        if(!b1&&!b2)
                            ins(zt,num);
                    }
                    else if(!b1&&!b2)
                        {if(mp[i+1][j]&&mp[i][j+1]) ins(zt+bin[j-1]+2*bin[j],num);}
                    else if(!b1&&b2) {
                        if(mp[i][j+1]) ins(zt,num);
                        if(mp[i+1][j]) ins(zt-bin[j]*b2+bin[j-1]*b2,num);
                    }
                    else if(b1&&!b2) {
                        if(mp[i][j+1]) ins(zt-bin[j-1]*b1+bin[j]*b1,num);
                        if(mp[i+1][j]) ins(zt,num);
                    }
                    else if(b1==1&&b2==1) {
                        int kl=1;
                        for(int t=j+1;t<=m;++t) {
                            if((zt>>(t*2))%4==1) ++kl;
                            if((zt>>(t*2))%4==2) --kl;
                            if(!kl) {ins(zt-bin[j]-bin[j-1]-bin[t],num);break;}
                        }
                    }
                    else if(b1==2&&b2==2) {
                        int kl=1;
                        for(int t=j-2;t>=0;--t) {
                            if((zt>>(t*2))%4==1) --kl;
                            if((zt>>(t*2))%4==2) ++kl;
                            if(!kl) {ins(zt+bin[t]-2*bin[j]-2*bin[j-1],num);break;}
                        }
                    }
                    else if(b1==2&&b2==1)
                        ins(zt-2*bin[j-1]-bin[j],num);
                    else if(i==e1&&j==e2)
                        ans+=num;
                }
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j) {
            char ch=getchar();
            while(ch!='*'&&ch!='.') ch=getchar();
            if(ch=='.') mp[i][j]=1,e1=i,e2=j;
        }
        bin[0]=1;for(int i=1;i<=12;++i) bin[i]=bin[i-1]<<2;
        work(),printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    mapreduce参数记录
    find命令使用中记录
    运算符的优先级(从高到低)
    常用字符与ASCII代码对照表
    mysql在liunx上使用记录
    Java 流收集器 ( Stream Collectors )
    CDH 删除Agent节点(退役节点)
    学习记录CombineFileInputFormat类
    读取HBases的数据的三种常见用法
    hash算法学习
  • 原文地址:https://www.cnblogs.com/King-of-Dark/p/13024338.html
Copyright © 2011-2022 走看看