玉米田

内存限制:128 MiB

时间限制:1000 ms

标准输入输出

题目类型:传统

评测方式:文本比较

题目描述

农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地。John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。

遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。

John想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)

输入格式

第一行:两个整数M和N,用空格隔开。

第2到第M+1行:每行包含N个用空格隔开的整数,描述了每块土地的状态。第i+1行描述了第i行的土地,所有整数均为0或1,是1的话,表示这块土地足够肥沃,0则表示这块土地不适合种草。

输出格式

一个整数,即牧场分配总方案数除以100,000,000的余数。

样例

样例输入

2 3

1 1 1

0 1 0

样例输出

9

(此题注意方案数要除以余数)

这道题很容易想到DP,并且是状压DP。为什么呢,设状态\(f_{i}\)为到第i行为止总的方案数,如果我们不能表示出\(i-1\)行的状态的话,那么第\(i\)行也推不出来。(第\(i\)行和第\(i-1\)行不能有土地邻接)

于是考虑状态压缩。用一个长度为\(m\)的二进制数\(j\)来表示第\(i\)行选择土地的情况,\(j\)的第\(k\)位为1表示在第\(i\)行的第\(k\)列选了一个土地。

于是我们便得到了状态转移方程:

\(f_{i,j} = \sum_{f_{i-1,k}}\)

那么这篇题解到这里就结束了

好吧别打我。

这道题的难点就是在于判断\(j\),\(k\),\(j\)和\(k\)这两个状态是否合法。这里就体现出了位运算的优越性。

对于判断一行农田\(j\)是否有相邻的已选的农田,我们可以这样判断:

if( (j<<1) & j)  不合法
else 合法

(位运算这篇博客里不会详讲,这种方法的可行性请读者自己翻阅资料思考)

同理对于状态\(k\)我们也可以这样判断。

对于上下相接的两个状态\(j\)和\(k\),我们要判断它们的每一位是否出现了都是1的情况:

if(i&j) 不合法
else 合法

(还有一个居然忘讲了)

需要注意的是,在枚举\(j\)的过程中,我们还要判断我们是否选择了“贫瘠”的土地,这是我使用的方法:

for(int i=1;i<=n;i++)  for(int j=1,L;j<=m;j++) {
cin>>L;
P[i]=(P[i]<<1)+L;
}//将初始的农田转换成2进制
for(int i=0;i<(1<<m);i++)
if((!((i<<1) & i)) && ((P[1] & i) == i))
f[1][i]=1; //初始化状态,((P[1] & i) == i)就是我用来判断是否
//选择了贫瘠土地的方法.

(关于状压DP,我这里要说一句,熟练掌握位运算是必要条件,这一点可以通过多做题来训练)

代码

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std; #define N 15
#define LL long long
#define MOD 100000000 LL n,m,f[15][100010],ans,P[N]; int main() {
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1,L;j<=m;j++) {
cin>>L;
P[i]=(P[i]<<1)+L;
}
for(int i=0;i<(1<<m);i++)
if((!((i<<1) & i)) && ((P[1] & i) == i))
f[1][i]=1;
for(int i=2;i<=n;i++)
for(int y=0;y<(1<<m);y++)
if((!((y<<1) & y)) && ((P[i] & y) == y))
for(int x=0;x<(1<<m);x++)
if((!((x<<1) & x)) && ((P[i-1] & x) == x)) {
if(x & y) continue;
f[i][y]=(f[i][y]+f[i-1][x])%MOD;
}
for(int i=0;i<(1<<m);i++)
if((!((i<<1) & i)) && ((P[n] & i) == i))
ans=(ans+f[n][i])%MOD;
cout<<ans;
}

状压DP : [USACO06NOV]玉米田的更多相关文章

  1. P1879 [USACO06NOV]玉米田Corn Fields(状压dp)

    P1879 [USACO06NOV]玉米田Corn Fields 状压dp水题 看到$n,m<=12$,肯定是状压鸭 先筛去所有不合法状态,蓝后用可行的状态跑一次dp就ok了 #include& ...

  2. P1879 [USACO06NOV]玉米田Corn Fields 状压dp/插头dp

    正解:状压dp/插头dp 解题报告: 链接! ……我真的太菜了……我以为一个小时前要搞完的题目调错误调了一个小时……90分到100我差不多搞了一个小时…… 然后这题还是做过的……就很气,觉得确实是要搞 ...

  3. [USACO06NOV]玉米田$Corn \ \ Fields$ (状压$DP$)

    #\(\mathcal{\color{red}{Description}}\) \(Link\) 农场主\(John\)新买了一块长方形的新牧场,这块牧场被划分成\(M\)行\(N\)列\((1 ≤ ...

  4. [USACO06NOV]玉米田Corn Fields 状压DP

    题面: 农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地.John打算在牧场上的某几格里种上美味的草,供他的 ...

  5. 状压DP【洛谷P1879】 [USACO06NOV]玉米田Corn Fields

    P1879 [USACO06NOV]玉米田Corn Fields 农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形 ...

  6. [USACO06NOV]玉米田Corn Fields (状压$dp$)

    题目链接 Solution 状压 \(dp\) . \(f[i][j][k]\) 代表前 \(i\) 列中 , 已经安置 \(j\) 块草皮,且最后一位状态为 \(k\) . 同时多记录一个每一列中的 ...

  7. 状压DP【p1879】[USACO06NOV]玉米田Corn Fields

    Description 农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地.John打算在牧场上的某几格里种上 ...

  8. 洛谷P1879 [USACO06NOV]玉米田Corn Fields(状压dp)

    洛谷P1879 [USACO06NOV]玉米田Corn Fields \(f[i][j]\) 表示前 \(i\) 行且第 \(i\) 行状态为 \(j\) 的方案总数.\(j\) 的大小为 \(0 \ ...

  9. 状压dp之二之三 炮兵阵地/玉米田 By cellur925

    一.简单的状压dp 玉米田 题目描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ ...

随机推荐

  1. Codeforces 990C (模拟+组合数学)

    题面: 传送门 分析: 此题O(n2l)" role="presentation" style="position: relative;">O( ...

  2. JavaScript之BOM操作

    一, 什么是BOM BOM:Browser Object Model,浏览器对象模型 BOM的结构图: 从上图也可以看出: window对象是BOM的顶层(核心)对象,所有对象都是通过它延伸出来的,也 ...

  3. 手写ORM持久层框架(转)

    工程结构: 本文测试的数据库为: 其中student的表结构为: 表数据: 配置文件 DB2.properties driver=com.mysql.jdbc.Driver url=jdbc\:mys ...

  4. SCUT - 106 - 花式ac - 主席树/启发式合并Treap

    https://scut.online/p/106 错在这组样例,发现是离散化之后,对k访问的时候也是应该访问离散化之后的k. 12 4 1 1 2 2 5 5 4 4 3 3 2 1 1 3 3 5 ...

  5. Django 的 logging日志文件配置

    在Django的settings配置文件里配置以下信息: import os BASE_LOG_DIR = os.path.join(BASE_DIR , "log") # log ...

  6. pppd - 点对点协议守护进程

    总览 SYNOPSIS pppd [ tty_name ] [ speed ] [ options ] 描述 点对点协议 (PPP) 提供一种在点对点串列线路上传输资料流 (datagrams)的方法 ...

  7. linux权限管理—基本权限

    目录 Linux权限管理-基本权限 一.权限的基本概述 二.权限修改命令chmod 三.基础权限设置案例 四.属主属组修改命令chown Linux权限管理-基本权限 一.权限的基本概述 1.什么是权 ...

  8. 【转】C/C++产生随机数

    转自:https://www.cnblogs.com/vectors07/p/8185215.html C/C++怎样产生随机数:这里要用到的是rand()函数, srand()函数,C语言/C++里 ...

  9. CentOS 7系统安装nginx+php

    安装介绍1.系统环境CentOS7 2.nginx版本1.12 3.PHP版本7.2 下载地址 4.MySQL版本5.7 安装nginx添加centos7的 nginx yum源 然后执行安装 sud ...

  10. javascript笔记收集

    因为前端编程的兴起, 慢慢地对css/javascript越来越淡, 偶尔用一下,得查半天资料. 这里就收藏一下比较生僻, 但是做工具时会用到的. json获取属性名 Object.keys(), 只 ...