CSU 1813 盖房子
来源:互联网 发布:逛淘宝 编辑:程序博客网 时间:2024/04/28 01:01
Description
Bobo 在 ICPCCamp 买了一块 n×m 的土地,其中有些格子是障碍。
他想选择两个矩形区域,建造两座房子。 很明显,用于盖房子的区域不能包含障碍。同时,两个区域不能相交(但是可以相邻)。
Bobo 想知道所有可能不同方案的数量除以 (109+7) 的余数。
Input
输入包含不超过 10 组数据。
每组数据的第一行包含两个整数 n,m (1≤n,m≤103).
接下来 n 行中的第 i 行包含一个长度为 m 的字符串 si。si 的第 j 位是 0 则表示第 i 行第 j 列的格子是空地,是 1 则表示该格子是障碍。
Output
对于每组数据,输出一个整数表示所求的值。
Sample Input
2 200013 4100000010100
Sample Output
5160
问选两块没有重复覆盖的全是0的矩阵的方案数。
按竖直方向把矩阵切成左右两块,显然左边合法数成上右边合法数是可行的。
再按照水平方向切两块,上边乘下边也是合法的。
这两种的和里重复统计的是左上乘右下和右上乘左下的部分,减去就是答案。
为了计算上述的内容,需要用单调栈快速算出以每个点为四个角落的可行矩形数量。
#include<set>#include<map>#include<ctime>#include<cmath>#include<stack>#include<queue>#include<bitset>#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>#include<functional>#define rep(i,j,k) for (int i = j; i <= k; i++)#define per(i,j,k) for (int i = j; i >= k; i--)#define loop(i,j,k) for (int i = j;i != -1; i = k[i])#define lson x << 1, l, mid#define rson x << 1 | 1, mid + 1, r#define ff first#define ss second#define mp(i,j) make_pair(i,j)#define pb push_back#define pii pair<int,int>#define in(x) scanf("%d", &x);using namespace std;typedef long long LL;const int low(int x) { return x&-x; }const double eps = 1e-9;const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 1e3 + 10;char s[N];int n, m;int c[N][N], a[N][N];LL ls[N][N], lx[N][N], rs[N][N], rx[N][N];void GetFour(){memset(c, 0, sizeof(c));rep(i, 1, n){rep(j, 1, m){if (a[i][j] || c[i][j]) continue;while (c[i][j] <= n - i && !a[i + c[i][j]][j]) c[i][j]++;rep(k, 2, c[i][j]) c[i + k - 1][j] = c[i][j] - k + 1;}int sum = 0; stack<pii> p;per(j, m, 1){pii now = mp(c[i][j], 1);while (!p.empty() && p.top().ff > now.ff){pii q = p.top(); sum -= q.ff * q.ss;now.ss += q.ss; p.pop();}sum += now.ff * now.ss;p.push(now);ls[i][j] = sum;}sum = 0; while (!p.empty()) p.pop();rep(j, 1, m){pii now = mp(c[i][j], 1);while (!p.empty() && p.top().ff > now.ff){pii q = p.top(); sum -= q.ff * q.ss;now.ss += q.ss; p.pop();}sum += now.ff * now.ss;p.push(now);rs[i][j] = sum;}}memset(c, 0, sizeof(c));per(i, n, 1){rep(j, 1, m){if (a[i][j] || c[i][j]) continue;while (c[i][j] < i && !a[i - c[i][j]][j]) c[i][j]++;rep(k, 2, c[i][j]) c[i - k + 1][j] = c[i][j] - k + 1;}int sum = 0; stack<pii> p;per(j, m, 1){pii now = mp(c[i][j], 1);while (!p.empty() && p.top().ff > now.ff){pii q = p.top(); sum -= q.ff * q.ss;now.ss += q.ss; p.pop();}sum += now.ff * now.ss;p.push(now);lx[i][j] = sum;}sum = 0; while (!p.empty()) p.pop();rep(j, 1, m){pii now = mp(c[i][j], 1);while (!p.empty() && p.top().ff > now.ff){pii q = p.top(); sum -= q.ff * q.ss;now.ss += q.ss; p.pop();}sum += now.ff * now.ss;p.push(now);rx[i][j] = sum;}}}int main(){while (scanf("%d%d", &n, &m) != EOF){rep(i, 0, n + 1) rep(j, 0, m + 1) ls[i][j] = rs[i][j] = 0;rep(i, 1, n){scanf("%s", s + 1);rep(j, 1, m) a[i][j] = s[j] - '0';}GetFour();LL L = 0, R = 0, ans = 0;rep(i, 1, n){rep(j, 1, m) (R += ls[i][j]) %= mod;(ans += L * R) %= mod; R = 0;rep(j, 1, m) (L += rx[i][j]) %= mod;}L = R = 0;rep(j, 1, m) {rep(i, 1, n) (R += ls[i][j]) %= mod;(ans += L * R) %= mod; R = 0;rep(i, 1, n) (L += rx[i][j]) %= mod;}rep(i, 1, n){rep(j, 1, m){rx[i][j] += rx[i - 1][j] + rx[i][j - 1] - rx[i - 1][j - 1];(ans -= rx[i][j] * ls[i + 1][j + 1]) %= mod;}per(j, m, 1){lx[i][j] += lx[i - 1][j] + lx[i][j + 1] - lx[i - 1][j + 1];(ans -= lx[i][j] * rs[i + 1][j - 1]) %= mod;}}printf("%lld\n", (ans + mod) % mod);}return 0;}
0 0
- CSU 1813 盖房子
- 盖房子
- 盖房子
- 盖房子
- JS小游戏 - 盖房子
- 盖房子_DP
- Vijos1057. 盖房子
- P1057 盖房子
- 盖房子优化1
- 盖房子优化2
- 盖房子优化3
- [Vijos1057] 盖房子
- 1057.盖房子
- vijos 1057 盖房子
- CillyB盖房子
- [vijos1057]盖房子
- [BZOJ1515]盖房子
- CillyB盖房子 QDU
- Oracle DUL Data Unloader数据恢复工具信息汇总
- 微信支付接口境内商户版、境内服务商版区别
- tjut 3016
- java按照月份把一个时间段拆分成多个时间区间
- boost库的shared_ptr剖析
- CSU 1813 盖房子
- 预防数据泄露——音乐播放器Spotify强制用户重置密码
- qt之工具栏的使用
- java中的链表
- SwipeTableView:搞定半糖首页列表布局效果
- FBI 旗下域名被“劫持”, Megaupload被黑入色情广告
- 利用WebStorm来管理你的Github
- Linux常用命令总结(2)
- java学习日记_22:面向对象之构造方法。07.11—12;