zoukankan      html  css  js  c++  java
  • luogu_1896【题解】状压DP

    题面:https://www.luogu.org/problemnew/show/P1896

    大意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

    状压DP

    用二进制表示当前状态。

    1表示有,0表示无。

    那么这个题的f[ i ][ j ][ w ]表示在第 i 行,状态为 j ,用了 w 个国王。

    方程见代码。

    其中bitset为二进制数位。

    a.count()表示二进制数中有多少个1。

    vis[ ]数组为符合条件的一行的状态。

    代码如下:

    #include<bits/stdc++.h>
    #define int long long
    #define rr register
    using namespace std;
    int n,m,ans=0;
    bool vis[1<<9];
    int f[10][1<<9][90],g[1<<9];
    signed main()
    {
        scanf("%lld%lld",&n,&m);
        for(rr int i=0;i<(1<<n);i++){
            if(!(i&(i<<1)) && !(i&(i>>1))) vis[i]=1;
            bitset <9> a(i);
            g[i]=a.count();
            if(vis[i]) f[1][i][g[i]]=1;
        }
        for(rr int i=2;i<=n;i++)
            for(rr int j=0;j<(1<<n);j++)
                if(vis[j])
                    for(rr int k=0;k<(1<<n);k++)///?
                        if(vis[k] && !(j&(k<<1)) && !(j&(k>>1)) && !(j&k))
                            for(rr int w=0;w+g[k]<=m;w++) 
                                f[i][k][w+g[k]]+=f[i-1][j][w];
        for(rr int i=0;i<(1<<n);i++) ans+=f[n][i][m];
        printf("%lld
    ",ans);
        // system("pause");
        return 0;
    }

    因为数据加强,记得开 long long。

  • 相关阅读:
    zoj 2876 Phone List
    zoj 2829 Beautiful Number
    zoj 2723 Semi-Prime(set)
    zoj 2835 Magic Square(set)
    zoj 2818 Root of the Problem
    zoj 2744 Palindromes
    zoj 1109 Language of FatMouse(map)
    zoj 2724 Windows Message Queue
    zoj 2722 Head-to-Head Match(两两比赛)
    zoj 2727 List the Books
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11129298.html
Copyright © 2011-2022 走看看