zoukankan      html  css  js  c++  java
  • 残缺棋盘--状压DP

    P1:给你一个n*m的残缺棋盘(部分位置不可放棋子),求棋子两两不能相邻的方案数mod987654321

    分析:这里相邻理解为四联通,我们将每一行看作一个状态,用上一行来推下一行的方案数。

    代码:

     1 #include "bits/stdc++.h"
     2 
     3 #define ll long long
     4 #define maxn 10
     5 #define maxm 10005
     6 using namespace std;
     7 
     8 int n, m, N, tot, s[maxm]; //s[i]表示第i种可行状态
     9 ll ans, f[maxn][maxm];    //f[i][j][l]表示第i行状态为第j种摆放的方案数
    10 int a[20][20];
    11 
    12 bool check(int id, int x) {
    13     for (int j = m; j >= 1; j--) {
    14         int y = x & 1;
    15         if (y == 1 && a[id][j] == 0)
    16             return 0;
    17         x >>= 1;
    18     }
    19     return 1;
    20 }
    21 int main() {
    22     cin >> n >> m;
    23     for (int i = 1; i <= n; i++)
    24         for (int j = 1; j <= m; j++) cin >> a[i][j];
    25 
    26     N = 1 << m;
    27     memset(f, 0, sizeof(f));
    28     for (int i = 0; i < N; ++i) {
    29         if (i & (i << 1))continue;
    30         s[++tot] = i;
    31         if (!check(1, s[tot])) continue;
    32         f[1][tot] = 1;    //第一行需要单独初始化
    33     }
    34     for (int i = 2; i <= n; ++i)
    35         for (int j = 1; j <= tot; ++j) {
    36             if (!check(i, s[j])) continue;
    37             for (int k = 1; k <= tot; ++k) {
    38                 if (s[j] & s[k])continue;
    39                 f[i][j] += f[i - 1][k];
    40             }
    41         }
    42     for (int i = 1; i <= tot; ++i) ans += f[n][i];
    43     printf("%lld", ans);
    44     return 0;
    45 }

    八联通的做法与之类似,改一下判断相邻条件即可。

  • 相关阅读:
    回首2016,展望2017
    认识多线程
    对CloseHandle用法的理解
    CDC、HDC、pDC之间的关系
    兼容位图和兼容DC的理解
    窗口中显示bmp图片的过程
    创建一个bmp格式的简单方法
    说明为什么Button控件不能使用CustomDraw技术
    MFC自绘Button按钮分析和实现
    VC之美化界面篇
  • 原文地址:https://www.cnblogs.com/mj-liylho/p/10908744.html
Copyright © 2011-2022 走看看