zoukankan      html  css  js  c++  java
  • LG P5056 【模板】插头dp

    Descriprion

    给出$n imes m$ 的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路。问有多少种铺法?

    Solution

    使用括号表示法记录状态,记1为 '(' ,2为 ')' ,0为无插头,分8种情况讨论:

    • 1:当前格子有障碍,此时必须下插头和右插头为0,转移后状态不变
    • 2:当前格子下插头和右插头为0,转移后右插头为1,下插头为2
    • 3:当前格子有右插头,无下插头,转移后右插头位置不变或向右移动一位
    • 4:当前格子有下插头,无右插头,转移后下插头位置不变或向左移动一位
    • 5:当前格子下插头和右插头为1,转移后从当前格子向右首个不匹配的2变为1
    • 6:当前格子下插头和右插头为2,转移后从当前格子向左首个不匹配的1变为2
    • 7:当前格子右插头为2,左插头为1,转移后删除两插头
    • 8:当前格子右插头为1,左插头为2,此时必须为最后一个可访问格子,更新总答案

    优化:使用链表存储状态为模数同余系的状态;滚动数组

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    int n,m,map[15][15],endx,endy,bits[15],pre=1,cur,tots[2],state[2][600000],head[600000],tot;
    const int mod=590027;
    long long ans,dp[2][600000];
    struct Edge
    {
        int to,nxt;
    }edge[600000];
    inline int read()
    {
        int f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            w=(w<<1)+(w<<3)+ch-'0';
            ch=getchar();
        }
        return f*w;
    }
    void insert(int sta,long long val)
    {
        int key=sta%mod;
        for(int i=head[key];i;i=edge[i].nxt)
        {
            if(state[cur][edge[i].to]==sta)
            {
                dp[cur][edge[i].to]+=val;
                return;
            }
        }
        tots[cur]++;
        state[cur][tots[cur]]=sta;
        dp[cur][tots[cur]]=val;
        edge[++tot]=(Edge){tots[cur],head[key]};
        head[key]=tot;
    }
    void DP()
    {
        tots[cur]=1;
        state[cur][1]=0;
        dp[cur][1]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=tots[cur];j++)
            {
                state[cur][j]<<=2;
            }
            for(int j=1;j<=m;j++)
            {
                tot=0;
                memset(head,0,sizeof(head));
                swap(cur,pre);
                tots[cur]=0;
                int nowsta=0,d=0,r=0;
                long long nowans=0;
                for(int k=1;k<=tots[pre];k++)
                {
                    nowsta=state[pre][k];
                    nowans=dp[pre][k];
                    d=(nowsta>>bits[j])%4;
                    r=(nowsta>>bits[j-1])%4;
                    if(!map[i][j])
                    {
                        if(!d&&!r)
                        {
                            insert(nowsta,nowans);
                        }
                    }
                    else if(!d&&!r)
                    {
                        if(map[i+1][j]&&map[i][j+1])
                        {
                            insert(nowsta+(1<<bits[j-1])+2*(1<<bits[j]),nowans);
                        }
                    }
                    else if(!d&&r)
                    {
                        if(map[i+1][j])
                        {
                            insert(nowsta,nowans);
                        }
                        if(map[i][j+1])
                        {
                            insert(nowsta-r*(1<<bits[j-1])+r*(1<<bits[j]),nowans);
                        }
                    }
                    else if(!r&&d)
                    {
                        if(map[i][j+1])
                        {
                            insert(nowsta,nowans);
                        }
                        if(map[i+1][j])
                        {
                            insert(nowsta-d*(1<<bits[j])+d*(1<<bits[j-1]),nowans);
                        }
                    }
                    else if(r==1&&d==1)
                    {
                        int cnt=1;
                        for(int l=j+1;l<=m;l++)
                        {
                            if((nowsta>>bits[l])%4==1)
                            {
                                cnt++;
                            }
                            else if((nowsta>>bits[l])%4==2)
                            {
                                cnt--;
                            }
                            if(!cnt)
                            {
                                insert(nowsta-(1<<bits[j-1])-(1<<bits[j])-(1<<bits[l]),nowans);
                                break;
                            }
                        }
                    }
                    else if(r==2&&d==2)
                    {
                        int cnt=1;
                        for(int l=j-2;l>=0;l--)
                        {
                            if((nowsta>>bits[l])%4==1)
                            {
                                cnt--;
                            }
                            else if((nowsta>>bits[l])%4==2)
                            {
                                cnt++;
                            }
                            if(!cnt)
                            {
                                insert(nowsta-2*(1<<bits[j-1])-2*(1<<bits[j])+(1<<bits[l]),nowans);
                                break;
                            }
                        }
                    }
                    else if(r==2&&d==1)
                    {
                        insert(nowsta-2*(1<<bits[j-1])-(1<<bits[j]),nowans);
                    }
                    else
                    {
                        if(i==endx&&j==endy)
                        {
                            ans+=nowans;
                        }
                    }
                }
            }
        }
    }
    int main()
    {
        n=read();
        m=read();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                char ch=0;
                while(ch!='.'&&ch!='*')
                {
                    ch=getchar();
                }
                if(ch=='.')
                {
                    map[i][j]=1;
                    endx=i;
                    endy=j;
                }
            }
        }
        for(int i=1;i<=14;i++)
        {
            bits[i]=i<<1;
        }
        DP();
        printf("%lld
    ",ans);
        return 0;
    }
    【模板】插头dp
  • 相关阅读:
    __name__使用方法,模块查找顺序和模块的绝对导入
    模块
    ATM程序结构
    迭代器
    常用内置方法
    生成式,匿名函数及内置函数部分使用方法
    算法之二分法和三元表达式
    redis配置文件
    PythonStudy——shutil 模块
    PythonStudy——pickle 模块 (泡菜)
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13398081.html
Copyright © 2011-2022 走看看