用状压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;
}

 

posted @ 2016-03-18 01:37  wwwsealss  阅读(541)  评论(0编辑  收藏  举报