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

5

160

问选两块没有重复覆盖的全是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
原创粉丝点击