用状压DP计算手机上九宫格的解锁方案数

Posted wwwsealss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用状压DP计算手机上九宫格的解锁方案数相关的知识,希望对你有一定的参考价值。

首先有两个限制条件:

1. 至少经过四个点。

2. 从一个点到另一个点,如果它们的连线上经过另外一点,如果这个点还没走过,那么必须经过,否则可以跳过这个中间点。

不熟悉限制条件的话可以自己去尝试一下~~~

状态数很少只有2^9,所以直接用状压DP搞起~~

dp[i][state]表示在状态state的情况下,最后停在节点i上的方案数,其中state是个二进制数,1表示这个位置的点已经过,0表示没有经过,那么状态转移方程是:

dp[j][state|(1<<j)]+=dp[i][state] 表示state状态下从i走到j~~~

枚举的过程中注意各种限制条件就好啦~~~

直接上代码:

int check[9][9];
int dp[10][600];

int main()
{
    memset(check, 0, sizeof(check));
    memset(dp, 0, sizeof(dp));
    check[0][8]=check[8][0]=4;
    check[0][2]=check[2][0]=1;
    check[3][5]=check[5][3]=4;
    check[6][8]=check[8][6]=7;
    check[2][6]=check[6][2]=4;
    check[0][6]=check[6][0]=3;
    check[1][7]=check[7][1]=4;
    check[2][8]=check[8][2]=5;
    for(int i=0;i<9;++i) dp[i][(1<<i)]=1;
    for(int i=1;i<(1<<9);++i)
        for(int j=0;j<9;++j)
            if(i&(1<<j))
                for(int k=0;k<9;++k)
                    if(!(i&(1<<k)))
                        if(!check[j][k]||(i&(1<<check[j][k])))
                            dp[k][i|(1<<k)]+=dp[j][i];
    int ans=0;
    for(int i=0;i<9;++i)
        for(int j=1;j<(1<<9);++j)
        {
            int k=j,cnt=0;
            while(k)
            {
                ++cnt;
                k=k&(k-1);
            }
            if(cnt>3) ans+=dp[i][j];
        }
    printf("%d\n",ans);
    return 0;
}

 

以上是关于用状压DP计算手机上九宫格的解锁方案数的主要内容,如果未能解决你的问题,请参考以下文章

5299. [CQOI2018]解锁屏幕状压DP

Mondriaan's Dream状压DP

[CQOI2018]解锁屏幕

「考试」省选73

UVa 11825 Hackers' Crackdown (状压DP)

[SCOI2005]互不侵犯