zoukankan      html  css  js  c++  java
  • 互不侵犯

    【题目描述】

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

    【输入描述】

    只有一行,包含两个数N、K(1 <= N <= 9,0 <= K <= N*N)。

    【输出描述】

    输出一行,包含一个整数,表示方案数。

    【样例输入】

    3 2

    【样例输出】

    16

    50分暴搜(暴力都不会写,我真是弱得无人能及!):

    源代码:
    
    #include<cstdio>
    int n,k,ans(0),x[8]={1,1,1,0,0,-1,-1,-1},y[8]={-1,0,1,1,-1,-1,0,1};
    bool f[10][10];
    void DFS(int X,int Y,int S) //如下图,一行接一行地搜索,避免重复,值得借鉴。
    {
        if (S==k)
        {
            ans++;
            return;
        }
        if ((n-X)*n+(n-Y)<=(k-S)) //A*优化。
          return;
        for (int a=X;a<=n;a++)
          for (int b=1;b<=n;b++)
            if (!f[a][b]&&(a>X||b>Y))
            {
                bool t(0);
                for (int c=0;c<8;c++)
                  if (f[a+x[c]][b+y[c]]) //值得借鉴,周围有国王就不成立。
                  {
                    t=true;
                    break;
                  }
                if (!t)
                {
                    f[a][b]=true;
                    DFS(a,b,S+1);
                    f[a][b]=false;
                }
            }
    }
    int main() //Re:从制杖开始的沙茶生活。
    {
        scanf("%d%d",&n,&k);
        for(int a=1;a<=n;a++)
          for(int b=1;b<=n;b++)
          {
            f[a][b]=true;
            DFS(a,b,1);
            f[a][b]=false;
          }
        printf("%d",ans);
        return 0;
    }
    
    /*
        *****
        *****
        **#..
        .....
        .....
        设当前点为"#",则搜索区域为"."。
    */

    状态压缩动态规划(正解):

    源代码:
    
    #include<cstdio>
    long long f[10][101][512],Ans; //注意数据类型。
    int M,N,K,Stay[101],Num[101]; //Stay[]记录每种状态压缩后的值,Num[]记录对应的状态中1的个数。
    bool Map[101][101];
    void DFS(int k,int Place,int Now) //k是放了几颗,Place是当前放的位置,Now是当前状态压缩后的值。
    {
        Stay[++M]=Now;
        Num[M]=k;
        if (k>=(N+1)/2||k>=K) //边界剪枝。
          return;
        for (int a=Place+2;a<=N;a++) //国王不相邻。
          DFS(k+1,a,Now+(1<<(a-1))); //注意,状态是颠倒的。
    }
    void Init()
    {
        DFS(0,-1,0); //预处理出一行的每种状态,共有M种。
        for (int a=1;a<=M;a++)
          for (int b=1;b<=M;b++)
            Map[a][b]=Map[b][a]=((Stay[a]&Stay[b])||((Stay[a]>>1)&Stay[b])||((Stay[a]<<1)&Stay[b]))?0:1; //预处理状态共存情况。
        for (int a=1;a<=M;a++)
          f[1][Num[a]][a]=1; //预处理边界。
    }
    int main() //状态压缩DP。
    {
        scanf("%d%d",&N,&K);
        Init();
        for (int a=2;a<=N;a++) //行数,1为边界,从2开始转移。
          for (int b=0;b<=K;b++) //棋子数。
            for (int Now=1;Now<=M;Now++) //这一行的情况。
            {
                if (Num[Now]>b) //大于所给棋子数,跳过。
                  continue;
                for (int k=1;k<=M;k++) //枚举上一行的状态。
                  if (Map[k][Now]&&Num[k]+Num[Now]<=b)
                    f[a][b][Now]+=f[a-1][b-Num[Now]][k]; //方案数转移。
            }
        for (int a=1;a<=M;a++) //总数统计。
          Ans+=f[N][K][a];
        printf("%lld",Ans);
        return 0;
    }
  • 相关阅读:
    3星|《葡萄酒经济学》:行业概况与资料汇编
    抖音、YouTube、Facebook等新媒体营销与运营相关14本书
    3星|《游戏学》:中美两国游戏产业概况
    3星|《新引爆点》:企业玩抖音入门
    4星|《未来的处方》:美国医疗组织应对奥巴马医改的成功经验12条
    2.5星|《知识付费》:行业相关资料的综述与堆砌
    《都挺好》原著小说大结局(严重剧透)
    OKR相关4本书,好书3本
    2.5星|《区块链超入门》:偏技术的介绍,没介绍过去两年间币圈的各种或狗血或精彩的故事与事故
    《经济学人》电子书15本,大部分水平较高
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5773908.html
Copyright © 2011-2022 走看看