Codeforces Round #689 (Div. 2, based on Zed Code Competition)B. Find the Spruce(dp + 重复利用)
B. Find the Spruce
题意
给你一个n行m列由*或者.组成的图形,一个图形高度为k时当且仅当满足\(1 \leq i \leq k\)时,第\(x + i - 1\)行必须满足在区间\([y - i + 1, y +i-1]\)全部都是'*'
思路
暴力解决方法
我们暴力判断当前行是否满足,如果满足我们继续将k加大然后继续向下判断,判断k的整个过程具有连续性,比如说当\(k=3\)时会重复判断\(k=2\)时的情况,所以直接继续判断即可。如果不满足则跳出。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 100;
typedef long long LL;
//#define int long long
char str[505][505];
int sum[505][505];
int n, m;
void solve() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
getchar();
for (int j = 1; j <= m; ++j) {
scanf("%c", &str[i][j]);
if (str[i][j] == '*') {
sum[i][j] = sum[i][j - 1] + 1;
}else sum[i][j] = sum[i][j - 1];
}
}
LL ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
for (int k = 1;; ++k) {
int l = i + k - 1;
int l1 = j - k + 1, r1 = j + k - 1;
if (l > n || l1 <= 0 || r1 > m) break;
if (sum[l][r1] - sum[l][l1 - 1] != 2 * k - 1) break;
++ans;
}
}
}
printf("%lld\n", ans);
}
signed main() {
int T = 1;
scanf("%d", &T);
// cin >> T;
while (T--) {
solve();
}
}
从下往上dp
如果当前point(i,j)是一个满足条件的图形,当且仅当\(str[i + 1][j - 1],str[i + 1][j], str[i+1][j+1] = '*'\)那么我们从下往上dp整个过程,注意取\(min\)
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 100;
typedef long long LL;
//#define int long long
char str[505][505];
int dp[505][505];
int n, m;
void solve() {
scanf("%d%d", &n, &m);
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; ++i) {
getchar();
for (int j = 1; j <= m; ++j) {
scanf("%c", &str[i][j]);
if (str[i][j] == '*') {
dp[i][j] = 1;
}
}
}
LL ans = 0;
for (int i = n; i >= 1; --i) {
for (int j = 1; j <= m; ++j) {
if(str[i][j] == '*') {
dp[i][j] = min({dp[i + 1][j - 1], dp[i + 1][j], dp[i + 1][ j + 1]}) + 1;
ans += dp[i][j];
}
}
}
printf("%lld\n", ans);
}
signed main() {
int T = 1;
scanf("%d", &T);
// cin >> T;
while (T--) {
solve();
}
}