• BZOJ1087 [SCOI2005] 互不侵犯King


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1087

    Description

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

    Input

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

    Output

    方案数。

    状态压缩DP初探。f[i][j][k]表示第i行,共放了j个国王,k表示当前该行的状态(状态压缩)。

    预处理过程为pre(),包括:

    1. 判断一行中的一个状态i是否合法(没有两个1相邻,国王之间不会在左右方向互相攻击),合法则c[i]=1;

    2. 计算一个合法状态i放了几个国王,记录在cnt[i]中;

    3. 判断两个状态i, j之间i转移到j是否合法(国王之间不会在上-下,左上-右下,左下-右上方向互相攻击),合法则valid[i][j]=1。

    小改了改代码时间从44ms变为28ms,看来单单减少循环就很重要了(然并卵,整整49个0ms……)

     1 #include <cstdio>
     2 #define rep(i,l,r) for(int i=l; i<=r; i++)
     3 #define clr(x,y) memset(x,y,sizeof(x))
     4 typedef long long ll;
     5 using namespace std;
     6 int n,m,all,cnt[512];
     7 ll ans,f[10][82][512];
     8 bool c[512],valid[512][512];
     9 void pre(){
    10     rep(i,0,all) if (!(i & (i >> 1))){
    11         int s = 0;
    12         for (int j=i; j; j>>=1) s += j & 1;
    13         cnt[i] = s; c[i] = 1;
    14     }
    15     rep(i,0,all) if (c[i])
    16     rep(j,0,all) if (c[j]){
    17         if ((!(i & j)) && (!(i & (j >> 1))) && (!(j & (i >> 1))))
    18         valid[i][j] = 1;
    19     }
    20 }
    21 int main(){
    22     scanf("%d%d",&n,&m); all = (1 << n) - 1;
    23     pre();
    24     rep(i,0,all) if (c[i]) f[1][cnt[i]][i] = 1;
    25     rep(i,1,n-1){
    26         rep(j,0,all) if (c[j])
    27         rep(k,0,all) if (c[k]){
    28             if (valid[j][k])
    29             for (int l=cnt[j]; l+cnt[k]<=m; l++)
    30             f[i+1][l+cnt[k]][k] += f[i][l][j];
    31         }
    32     }
    33     rep(i,0,all) ans += f[n][m][i];
    34     printf("%lld
    ",ans);
    35     return 0;
    36 }
    View Code
  • 相关阅读:
    NXOpen 创建方体block代码
    Mysql---2 DDL DML DQL DCL
    Mysql数据库--1数据库操作
    FFmpeg
    Servlet Web
    Java web Springboot
    Java 网络
    Java 注解 反射
    Java 线程状态
    Java Lambda
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj1087.html
Copyright © 2020-2023  润新知