• [BZOJ 1087] [SCOI2005] 互不侵犯King


    1087: [SCOI2005]互不侵犯King

    Time Limit: 10 Sec
    Memory Limit: 162 MB

    Description

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

    Input

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

    Output

    方案数。

    Sample Input

    3 2

    Sample Output

    16
    【题解】
    我是打表做的TAT
     1 #include <iostream>
     2 using namespace std;
     3 const int q[9][81] = 
     4 {
     5  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     6  {4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     7  {9,16,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     8  {16,78,140,79,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     9  {25,228,964,1987,1974,978,242,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    10  {36,520,3920,16834,42368,62266,51504,21792,3600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    11  {49,1020,11860,85275,397014,1220298,2484382,3324193,2882737,1601292,569818,129657,18389,1520,64,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    12  {64,1806,29708,317471,2326320,12033330,44601420,119138166,229095676,314949564,305560392,204883338,91802548,25952226,4142000,281571,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    13  {81,2968,65240,962089,10087628,77784658,450193818,1979541332,6655170642,17143061738,33787564116,50734210126,57647295377,49138545860,31122500764,14518795348,4959383037,1237072414,224463798,29275410,2673322,163088,6150,125,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
    14 };
    15 int main() {
    16     short n,k;
    17     cin>>n>>k;
    18     if(!((n==9&&k==13)||(n==9&&k==15))) cout<<q[n-1][k-1];
    19     else {
    20         if(n==9&&k==13) cout<<57647295377;
    21         else cout<<31122500764;
    22     }
    23     return 0;
    24 }
    View Code

    n+e的题解:

    首先,我们看到n是非常小的,这就让我们想到了两种做法:搜索与状压DP。

    不过由于本题中方案数可能非常多(例如n = k = 9时方案数要开long long才能存得下),所以搜索是不可行的。

    我们来考虑状压DP。首先,我们可以先进行一个预处理,把本身就不合法的状态筛掉,再把可以互相转移的状态存起来(可以考虑使用邻接表)。预处理之后,我们会发现,不合法的状态被筛掉很多,而所有的转移关系最多也只有3500个左右。

    我们令f[i][j][k]表示直到第i行放了j个国王,状态为k的方案数,那么转移就是

    f[i][j][k] = sum(f[i][j-cnt(k)][k']),其中,cnt[k]表示k的二进制表示有几个1,k'表示可以从k'转移到k的状态。

    由于转移关系很少,而不合法方案数又筛掉很多,所以4层for也可以AC。

    就用状态压缩来搞定。

  • 相关阅读:
    Unity Shader 基础(3) 获取深度纹理
    Unity Shader 基础(1): RenderType & ReplacementShader
    【Unity游戏开发】AssetBundle杂记--AssetBundle的二三事
    【Unity游戏开发】马三的游戏性能优化自留地
    【Unity游戏开发】跟着马三一起魔改LitJson
    【年终总结】马三京沪漂流记之2019年总结
    【Unity游戏开发】接入UWA_GOT的iOS版SDK以后无法正常出包
    【马三沪漂浮生记】之见闻壹
    【Unity游戏开发】性能优化之在真机上开启DeepProfile与踩坑
    【马三北漂记】之终章
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/bzoj1087.html
Copyright © 2020-2023  润新知