传送门:点击打开链接
题意:告诉你一个地图(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;
}
本文介绍了一种算法,用于解决在一个包含障碍物的地图中,计算特定子矩阵内最多可以放置多少个1*2的多米诺牌的问题。通过动态规划预先计算地图上每个子矩阵的解决方案,并利用预处理数组快速得出任意给定子矩阵内的答案。

1万+

被折叠的 条评论
为什么被折叠?



