对于此题的性质我们考虑DP

分四种情况

黑色块在右侧单调降,单调升

还有在左侧

另外我们这样可能会记重,所以还要将重复记过的也就是边界线是横的和竖的

然后还要将全白全黑加上

  1 #include<bits/stdc++.h>
2 #define MAXN 2100
3 #define int long long
4 using namespace std;
5 int f[5][MAXN][MAXN];
6 int sum[5][MAXN][MAXN];
7 int n,m;
8 const int mod=1e9+7;
9 char c[MAXN][MAXN];
10 int jud[2][MAXN][MAXN];
11 int jud_sum[2][MAXN][MAXN];
12 void work(int k,int cal)
13 {
14 f[k][0][m]=1;
15 for(int i=1;i<=n;++i)//黑色单降靠左
16 {
17 sum[k][i-1][m]=f[k][i-1][m];
18 for(int j=m-1;j>=0;--j)
19 {
20 sum[k][i-1][j]=(sum[k][i-1][j+1]+f[k][i-1][j])%mod;
21 //printf("sum[%lld][%lld][%lld]=%lld\n",k,i-1,j,sum[k][i-1][j]);
22 }
23 for(int j=0;j<=m;++j)
24 {
25 //printf("i%lld j=%lld jud%lld %lld\n",i,j,jud[cal][i][j],(jud[cal^1][i][m]-jud[cal^1][i][j]));
26 if(j!=0)
27 if(jud[cal][i][j]!=0||(jud[cal^1][i][m]-jud[cal^1][i][j])!=0){continue;}
28 if(j==0)
29 if(jud[cal][i][j]||jud[cal^1][i][m]){continue;}
30 f[k][i][j]=sum[k][i-1][j]%mod;
31 //printf("f[%lld][%lld][%lld]=%lld\n",k,i,j,f[k][i][j]);
32 }
33 }
34 f[k+1][0][0]=1;
35 for(int i=1;i<=n;++i)//黑色单升靠左
36 {
37 sum[k+1][i-1][0]=f[k+1][i-1][0];
38 for(int j=1;j<=m;++j)
39 {
40 sum[k+1][i-1][j]=(sum[k+1][i-1][j-1]+f[k+1][i-1][j])%mod;
41 }
42 for(int j=0;j<=m;++j)
43 {
44 if(j)
45 if(jud[cal][i][j]||(jud[cal^1][i][m]-jud[cal^1][i][j]))continue;
46 if(j==0)
47 if(jud[cal][i][j]||jud[cal^1][i][m])continue;
48 f[k+1][i][j]=sum[k+1][i-1][j]%mod;
49 //printf("f[%lld][%lld][%lld]=%lld\n",k+1,i,j,f[k+1][i][j]);
50 }
51 }
52 }
53 int ans=0;
54 int get_sum(int k,int x1,int y1,int x2,int y2)
55 {
56 if(x1>x2)return 0;if(y1>y2)return 0;
57 return (jud_sum[k][x2][y2]-jud_sum[k][x1-1][y2]-jud_sum[k][x2][y1-1]+jud_sum[k][x1-1][y1-1]+mod)%mod;
58 }
59 void work2()
60 {
61 for(int i=0;i<=n;++i)
62 {
63 if(get_sum(1,1,1,i,m)==0&&get_sum(0,i+1,1,n,m)==0)
64 {
65 ans--;
66 }
67 }
68 for(int i=0;i<=n;++i)
69 {
70 if(get_sum(0,1,1,i,m)==0&&get_sum(1,i+1,1,n,m)==0)
71 {
72 ans--;
73 }
74 }
75 for(int i=0;i<=m;++i)
76 {
77 if(get_sum(0,1,1,n,i)==0&&get_sum(1,1,i+1,n,m)==0)
78 {
79 ans--;
80 }
81 }
82 for(int i=0;i<=m;++i)
83 {
84 if(get_sum(1,1,1,n,i)==0&&get_sum(0,1,i+1,n,m)==0)
85 {
86 ans--;
87 }
88 }
89 if(get_sum(1,1,1,n,m)==0)ans++;
90 if(get_sum(0,1,1,n,m)==0)ans++;
91 }
92 signed main()
93 {
94 scanf("%lld%lld",&n,&m);
95 for(int i=1;i<=n;++i)
96 {
97 scanf("%s",c[i]+1);
98 for(int j=1;j<=m;++j)
99 {
100 jud[0][i][j]+=jud[0][i][j-1];
101 jud[1][i][j]+=jud[1][i][j-1];
102 jud_sum[0][i][j]=(jud_sum[0][i-1][j]+jud_sum[0][i][j-1]-jud_sum[0][i-1][j-1])%mod;
103 jud_sum[1][i][j]=(jud_sum[1][i-1][j]+jud_sum[1][i][j-1]-jud_sum[1][i-1][j-1])%mod;
104 if(c[i][j]=='B'){jud[0][i][j]++;jud_sum[0][i][j]++;}
105 if(c[i][j]=='W'){jud[1][i][j]++;jud_sum[1][i][j]++;}
106 }
107 }
108 work(1,1);
109 work(3,0);
110 for(int k=1;k<=4;++k)
111 {
112 for(int i=0;i<=m;++i)
113 {
114 ans=(ans+f[k][n][i])%mod;
115 //printf("f[%lld][%lld][%lld]=%lld\n",k,n,i,f[k][n][i]);
116 }
117 }
118 //printf("初ans=%lld\n",ans);
119 work2();
120 printf("%lld\n",ans%mod);
121 }

「模拟8.23」阴阳 DP的更多相关文章

  1. 「模拟8.23」one递推,约瑟夫

    前置芝士约瑟夫问题 这样大概就是板子问题了 考场的树状数组+二分的60分暴力??? 1 #include<bits/stdc++.h> 2 #define int long long 3 ...

  2. 「模拟赛20190327」 第二题 DP+决策单调性优化

    题目描述 小火车虽然很穷,但是他还是得送礼物给妹子,所以他前往了二次元寻找不需要钱的礼物. 小火车准备玩玩二次元的游戏,游戏当然是在一个二维网格中展开的,网格大小是\(n\times m\)的,某些格 ...

  3. 「模拟赛20181025」御风剑术 博弈论+DP简单优化

    题目描述 Yasuo 和Riven对一排\(n\)个假人开始练习.斩杀第\(i\)个假人会得到\(c_i\)个精粹.双方轮流出招,他们在练习中互相学习,所以他们的剑术越来越强.基于对方上一次斩杀的假人 ...

  4. 「模拟赛20191019」B 容斥原理+DP计数

    题目描述 将\(n\times n\)的网格黑白染色,使得不存在任意一行.任意一列.任意一条大对角线的所有格子同色,求方案数对\(998244353\)取模的结果. 输入 一行一个整数\(n\). 输 ...

  5. 「模拟赛20191019」A 简单DP

    题目描述 给一个\(n\times m\)的网格,每个格子上有一个小写字母. 对于所有从左上角\((1,1)\)到右下角\((n,m)\)只向下或向右走的路径构成的集合,判断是否存在两条走法不同的路径 ...

  6. 「模拟8.21」山洞(矩阵优化DP)

    暴力: 正解: 考虑循环矩阵,f[i][j]表示从i点到j点的方案数 我们发现n很小,我们预处理出n次的f[i][j] 然后在矩阵快速幂中,我们要从当前的f[i][j]*f[j][k]-->fi ...

  7. 2021升级版微服务教程5—通过IDEA运行多个项目实例「模拟集群」

    2021升级版SpringCloud教程从入门到实战精通「H版&alibaba&链路追踪&日志&事务&锁」 教程全目录「含视频」:https://gitee.c ...

  8. 「模拟赛20180306」回忆树 memory LCA+KMP+AC自动机+树状数组

    题目描述 回忆树是一棵树,树边上有小写字母. 一次回忆是这样的:你想起过往,触及心底--唔,不对,我们要说题目. 这题中我们认为回忆是这样的:给定 \(2\) 个点 \(u,v\) (\(u\) 可能 ...

  9. 「模拟赛 2018-11-02」T3 老大 解题报告

    老大 题目描述 因为 OB 今年拿下 4 块金牌,学校赞助扩建劳模办公室为劳模办公室群,为了体现 OI 的特色,办公室群被设计成了树形(n 个点 n − 1 条边的无向连通图),由于新建的办公室太大以 ...

随机推荐

  1. 去了字节跳动,才知道年薪40W的测试有这么多?

    最近脉脉职言区有一条讨论火了: 哪家互联网公司薪资最'厉害'? 下面的评论多为字节跳动,还炸出了很多年薪40W的测试工程师   我只想问一句,现在的测试都这么有钱了吗? 前几天还有朋友说,从腾讯跳槽去 ...

  2. 射线与空间内三角形的相交检测算法(Möller-Trumbore)的推导与实践

    背景介绍(学习算法之前需要先了解) 射线与空间内三角形的相交检测是游戏程序设计中一个常见的问题,最典型的应用就是拾取(Picking),本文介绍一个最常见的方法,这个方法也是DirectX中采用的方法 ...

  3. 【敏杰开发】Beta阶段项目展示

    [敏杰开发]Beta阶段项目展示 项目相关地址汇总 线上地址:http://roadmap.imcoming.top 前端仓库:https://github.com/MinJieDev/Roadmap ...

  4. 普里姆算法(Prim)

    概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图(带权图)里搜索最小生成树.即此算法搜索到的边(Edge)子集所构成的树中,不但包括了连通图里的所有顶点(Vertex)且其所有边的权 ...

  5. KVM 添加新硬件

    1 显卡 spice 2视频 qxl驱动 3 声音 ich6最好  ich9最清楚 4 输入 鼠标 智能图   否则不能VNC找不到焦点 5 磁盘大小 至少80G 否则 无法自动安装  无swap和 ...

  6. Ubuntu20 修改网卡名称

    Ubuntu 修改网卡名称 Ubuntu修改网卡名称 Ubuntu 版本: Ubuntu 20.04 查看当前网卡名称 root@it:~# ip add 1: lo: <LOOPBACK,UP ...

  7. django访问mysql数据库--模型(model)

    一.安装: sudo pip install mysql-connector-python sudo pip install MySQL-python 异常情况,如果提示pip超时 curl http ...

  8. Ansible命令行方式执行

    Ansible ad-hoc 什么是ad-hoc? 临时命令,执行完不会保存,类似于批量执行命令. ansible的选项 -i # 指定主机清单 ansible rsync -m ping -i 1. ...

  9. 血缘关系分析工具SQLFLOW--实践指南

    SQLFlow 是用于追溯数据血缘关系的工具,它自诞生以来以帮助成千上万的工程师即用户解决了困扰许久的数据血缘梳理工作. 数据库中视图(View)的数据来自表(Table)或其他视图,视图中字段(Co ...

  10. 2. Servlet3.0注解方式 @WebServlet

    web.xml配置还是比较麻烦,这次使用注解方式 编写servlet import javax.servlet.ServletException; import javax.servlet.annot ...