传送门:点击打开链接
题意:告诉你一个地图(5e2*5e2),里面有障碍物,现在告诉你地图里面的一个子矩阵的对角点坐标,求这个子矩阵里能放多少个1*2的多米诺牌
思路:求dp[i][j]表示(1,1)到(i,j)这个子矩阵的的答案,A[i][j]表示第i行的前j列的答案,b[i][j]表示第i列的前j行的答案
那么对于(bx,by),(ex,ey),答案就等于dp[ex][ey]-dp[ex][by]-dp[bx][ey]+dp[bx][by]+A[bx][ey]-A[bx][by-1]+B[by][ex]-B[by][bx-1]
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iomanip> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; typedef pair<int, int>PII; const int MX = 500 + 2; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; int n, m; char s[MX][MX]; int dp[MX][MX], A[MX][MX], B[MX][MX]; void prosolve() { memset(dp, 0, sizeof(dp)); memset(A, 0, sizeof(A)); memset(B, 0, sizeof(B)); for(int ex = 1; ex <= n; ex++) { int cnt = 0; for(int ey = 1; ey <= m; ey++) { if(1 < ey && s[ex][ey] == '.' && s[ex][ey - 1] == '.') cnt++; if(1 < ex && s[ex][ey] == '.' && s[ex - 1][ey] == '.') cnt++; dp[ex][ey] = dp[ex - 1][ey] + cnt; } } for(int ex = 1; ex <= n; ex++) { for(int ey = 1; ey <= m; ey++) { A[ex][ey] = A[ex][ey - 1]; if(1 < ey && s[ex][ey] == '.' && s[ex][ey - 1] == '.') A[ex][ey]++; } } for(int ey = 1; ey <= m; ey++) { for(int ex = 1; ex <= n; ex++) { B[ey][ex] = B[ey][ex - 1]; if(1 < ex && s[ex][ey] == '.' && s[ex - 1][ey] == '.') B[ey][ex]++; } } } int main() { //FIN; while(~scanf("%d%d", &n, &m)) { for(int i = 1; i <= n; i++) { scanf("%s", s[i] + 1); } prosolve(); int Q; scanf("%d", &Q); while(Q--) { int bx, by, ex, ey; scanf("%d%d%d%d", &bx, &by, &ex, &ey); int ans = dp[ex][ey] - dp[ex][by] - dp[bx][ey] + dp[bx][by]; ans += A[bx][ey] - A[bx][by]; ans += B[by][ex] - B[by][bx]; printf("%d\n", ans); } } return 0; }