2018年全国多校算法寒假训练营练习比赛(第二场)F - 德玛西亚万岁

链接:https://www.nowcoder.com/acm/contest/74/F
来源:牛客网

题目描述

德玛西亚是一个实力雄厚、奉公守法的国家,有着功勋卓著的光荣军史。

这里非常重视正义、荣耀、职责的意识形态,这里的人民为此感到强烈自豪。

有一天他们想去制裁邪恶的比尔吉沃特,于是派遣了自己最优秀的战士。

结果比尔吉沃特领土太小,只有长为n宽为m共计n*m块土地,其中有些土

地标记为0表示为高山峻岭或者深海湖泊,英雄们无法在其中站立,只有标

记为1的土地才能容纳一个英雄。德玛西亚的英雄们战斗时有一个特点,他

们不希望队友站在自己旁边显得很暧昧。请问最多能有多少种安排德玛西

亚英雄的方法?

输入描述:

输入包含多组测试数据;每组数据的第一行包含2个整数n和m (n <= 12, m <= 12 ),之间用空格隔开;接下来的n行,每行m个数,表示n*m的比尔吉沃特领土。

输出描述:

输出一个整数n代表安排应用的方法。(答案取膜100000000)
输入例子:
3 3
1 1 1
0 1 1
1 0 0
输出例子:
24

-->

示例1

输入

3 3
1 1 1
0 1 1
1 0 0

输出

24

题解

状压$dp$。

$dp[i][j][k]$表示到第$i$层,放置了$j$个人,且第$i$层的放置状态为$k$的方案数。

有很多优化可以做,没做优化也可以过。

#include <bits/stdc++.h>
using namespace std;

int n, m;
int a[20][20];
int h[20];

long long dp[15][80][4100];
long long mod = 100000000LL;
int cnt[4100], error[4100];

int limit = 75;

int lowbit(int x) {
  return x & (-x);
}

void init() {
  for(int i = 1; i < (1 << 12); i ++) {
    cnt[i] = cnt[i - lowbit(i)] + 1;
  }
  for(int i = 0; i < (1 << 12); i ++) {
    for(int j = 0; j < 12; j ++) {
      int A = i & (1 << j);
      int B = i & (1 << (j + 1));
      if(A && B) error[i] = 1;
    }
  }
}

int main() {
  init();
  while(~scanf("%d%d", &n, &m)) {
    for(int i = 1; i <= n; i ++) {
      h[i] = 0;
      for(int j = 0; j < m; j ++) {
        scanf("%d", &a[i][j]);
        h[i] = h[i] * 2 + a[i][j];
      }
    }

    dp[0][0][0] = 1;
    for(int i = 1; i <= n; i ++) {
      for(int num = 0; num <= limit; num ++) {
        for(int now = 0; now < (1 << m); now ++) {
          dp[i][num][now] = 0;
          if(error[now]) continue;
          if((now | h[i]) != h[i]) continue;
          if(num - cnt[now] < 0) continue;

          for(int pre = 0; pre < (1 << m); pre ++) {
            if(error[now]) continue;
            if(pre & now) continue;
            dp[i][num][now] = (dp[i][num][now]
                               + dp[i - 1][num - cnt[now]][pre]) % mod;
          }
        }
      }
    }
    long long ans = 0;
    for(int num = 0; num <= limit; num ++) {
      for(int now = 0; now < (1 << m); now ++) {
        ans = (ans + dp[n][num][now]) % mod;
      }
    }
    printf("%lld\n", ans);

  }
  return 0;
}

原文地址:https://www.cnblogs.com/zufezzt/p/8371719.html

时间: 2024-10-10 12:46:07

2018年全国多校算法寒假训练营练习比赛(第二场)F - 德玛西亚万岁的相关文章

【题集】牛客网&#183;2018年全国多校算法寒假训练营练习比赛(第二场)

原文链接:2018年全国多校算法寒假训练营练习比赛(第二场) A 吐泡泡 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K64bit IO Format: %lld 题目描述 小鱼儿吐泡泡,嘟嘟嘟冒出来.小鱼儿会吐出两种泡泡:大泡泡"O",小泡泡"o". 两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉. (是的你没看错,小气泡和大气泡不会产生任何变化的,原因我也不知道.) 例如:ooOOoooO经过一段时间

2018年全国多校算法寒假训练营练习比赛(第一场)G.圆圈

链接:https://www.nowcoder.com/acm/contest/67/G来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 圈圈圆圆圈圈,lulu小朋友最近看喜羊羊看多了,老是受刺激就画圆圈,听到小于8的数字时,还会画出十分有规律的圆圈,现在你需要根据样例观察出规律,编写程序,根据输入的数字n(n<8),输出对应的圆圈. 输入描述: 第一行是样例数T(T<9)第2

2018年全国多校算法寒假训练营练习比赛(第一场)D N阶汉诺塔变形

https://www.nowcoder.com/acm/contest/67/D 思路: 先手动模拟一下过程,以下是模拟过程,按顺序表示第几步需要移动的盘标号 1 1 2 1 1 2 1 1 3 1 1 2 1 1 2 1 1 3 1 1 2 1 1 2 1 1 4 1 1 2 ...... 我们发现每出现两次1就会出现一次2,每两次2就会出现一次3,每两次3就会出现一次4,每两次4就会出现一次5...... 然后我们发现如果把所有大于1的标号看成1,那么k步1出现的次数是 k/1 如果把所有

2018年全国多校算法寒假训练营练习比赛(第二场)

A题: 链接:https://www.nowcoder.com/acm/contest/74/A来源:牛客网 小鱼儿吐泡泡,嘟嘟嘟冒出来.小鱼儿会吐出两种泡泡:大泡泡"O",小泡泡"o". 两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉. (是的你没看错,小气泡和大气泡不会产生任何变化的,原因我也不知道.) 例如:ooOOoooO经过一段时间以后会变成oO. 输入描述: 数据有多组,处理到文件结束.每组输入包含一行仅有'O'与'o'组成的字符串. 输出描述

2018年全国多校算法寒假训练营练习比赛(第二场)A.吐泡泡

原题链接 描述 小鱼儿吐泡泡,嘟嘟嘟冒出来.小鱼儿会吐出两种泡泡:大泡泡"O",小泡泡"o". 两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉. (是的你没看错,小气泡和大气泡不会产生任何变化的,原因我也不知道.) 注意:自左到右进行合并. 例如:ooOOoooO经过一段时间以后会变成oO. 输入 数据有多组,处理到文件结束. 每组输入包含一行仅有'O'与'o'组成的字符串. 输出 每组输出仅包含一行,输出一行字符串代表小鱼儿吐出的泡泡经过融合以后所剩余的

【2018年全国多校算法寒假训练营练习比赛(第三场)】

之前题目比较水,今天的还可以. [A 不凡的大夫] 方法一:答案是log8(n!),解决方案是预处理,将需要的答案记录下来以免超内存: 方法二:用公式,斯特林公式:    [B 一个小问题] 题解:线性同余方程组,一看就不是中国剩余定理,当心. [C 守护白起] 题解:polya..... [D 小牛vs小客] 题解:博弈,做过不久. [E 进击吧!阶乘] 题解:高精度裸题. [F 小牛再战] 题解:博弈,看看第一步能不能控制住对方. [G 大水题] 题解:简单容斥定理. [H 向左走] 一眼不

2018年全国多校算法寒假训练营练习比赛(第三场) 小牛再战(博弈)

链接:https://www.nowcoder.net/acm/contest/75/F来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 共有N堆石子,已知每堆中石子的数量,两个人轮流取石子,每次只能选择N堆石子中的一堆取一定数量的石子(最少取一个),取过子之后,还可以将该堆石子中剩余的石子随意选取几个放到其它的任意一堆或几堆上.等哪个人无法取子时就表示此人输掉了游戏.注意:一堆

2018年全国多校算法寒假训练营练习比赛(第四场)题解

[题目链接] A - 石油采集 题意:有一个$01$矩阵,每次可以拿走两个相邻的$1$,问最多能操作几次. 这题和HDU 1507一样.二维矩阵四连通图是一个二分图,题目的操作事实上就是求这个二分图的最大匹配. B - 道路建设 最小生成树 #include <bits/stdc++.h> using namespace std; const int maxn = 2e5 + 10; int f[maxn]; struct Edge { int u, v, cost; }s[maxn]; bo

2018年全国多校算法寒假训练营练习比赛(第四场)nowcoder

A. 石油采集 题意:给你一个n*n的方格,n小于50,每个方格中'.'代表水,'#'代表油.每次你可以收集两个相邻方格里的油.问你最多能收集几次. 观察:有点像用1*2的多米诺骨牌覆盖棋盘问题,求一下二分图最大匹配. code: 1 /* 2 by skydog 3 */ 4 #include <iostream> 5 #include <cstdio> 6 #include <vector> 7 #include <utility> 8 #include