zoukankan      html  css  js  c++  java
  • [SCOI2005]互不侵犯King

    题目描述

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

        ——by洛谷

        https://www.luogu.org/problem/show?pid=1896



       显然的棋盘模型的状压DP,故考虑对每行二进制状压,状压为表示有无王的01串,再由题意得到如下的限制:

    • 每个串中不存在连续两个以上的1
    • 相邻两串的同列不存在同为1的情况
    • 不存在与上一行左侧或右侧同为1的情况

        于是对于限制一,可在预处理中实现;对于二三,可在转移时限制,得出状态转移方程:

        f[i][j][l+c[j]]=Σf[i-1][k][l];(i:当前行数;j:枚举本行所有可能状态,l+c[j]:此时的王的个数,c[j]:状态s[j]中王的个数)

    然后对k进行限制,s[j]&s[k]==0,s[j]&(s[k]<<1)==0,s[j]&s[k]>>1)==0;之类的

        需要注意的是:

    • dfs预处理
    • 处理好c[j]

    总结:简单的DP么

    代码如下:

    #include<cstdio>
    using namespace std;
    long long f[10][1000][100];
    int s[100],c[100];
    int man;
    int n,m;
    void dfs(int ,int ,int ,int );
    int main()
    {
        int i,j,k,l;
        long long ans=0;
        scanf("%d%d",&n,&m);
        dfs(1,0,0,0);
            f[0][1][0]=1;
        for(i=1;i<=n;i++)
            for(j=1;j<=man;j++)
                for(k=1;k<=man;k++)
                if((s[j]&s[k])==0&&(s[j]&(s[k]<<1))==0&&(s[j]&(s[k]>>1))==0)
                    for(l=c[k];l<=m-c[j];l++)
                        f[i][j][l+c[j]]+=f[i-1][k][l];
        for(i=1;i<=man;i++)
            ans+=f[n][i][m];
        printf("%lld",ans);
        return 0;
    }
    
    void dfs(int now,int num,int ma,int p)
    {
        int i;
        if(ma>m)return;
        if(now==n+1)
        {
            s[++man]=num;
            c[man]=ma;
            return;
        }
        for(i=0;i<=1;i++)
        if(1-p>=i)
            dfs(now+1,num+i*(1<<(now-1)),ma+i,i);
    }

    祝AC哟;

    Just close your eyes, you`ll be alright, no one can hurt you after you die.
  • 相关阅读:
    Maven导入com.google.common.collect jar包
    poj 2192 Zipper
    poj 3278 Catch That Cow
    poj 2488 A Knight's Journey
    poj 3982 序列
    poj 2109 Power of Cryptography
    poj 3258 3273
    java中大数的一些基本运算
    hdu 1715 大菲波数
    最小生成树模板
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/6160219.html
Copyright © 2011-2022 走看看