题解:B4293 [蓝桥杯青少年组省赛 2022] 奖品
Dongze2010 · · 题解
B4293 奖品
题目大意
给你一个
题目分析
不用前缀和,直接查找的时间复杂度约为
所以最好使用前缀和。我们可以通过前缀和或动态规划,将复杂度降至
若有二维
| 6 | 1 | 3 | 4 |
|---|---|---|---|
| 2 | 4 | 5 | 3 |
| 5 | 1 | 2 | 3 |
| 其对应的 |
6 | 7 | 10 | 14 |
|---|---|---|---|---|
| 8 | 13 | 21 | 28 | |
| 13 | 19 | 29 | 39 |
二维前缀和计算。
cin >> a[i][j]; //输入
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i][j];
//计算二维前缀和
输入并计算前缀和。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 114;
int n,m,a[maxn][maxn],sum[maxn][maxn];
int main(){
cin >> n >> m;
for (int i = 1;i <= n;i++){
for (int j = 1;j <= m;j++){
cin >> a[i][j];
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i][j];
}
}
return 0;
}
接下来的判断怎么写呢?
我们可以从正方形的对角线入手。
因为一个点若在正方形的对角线上,它就既可以当做这个正方形的左上(下)点,或右上(下)点。这里为遍历方便,只考虑正方形的左上和右上点。
当
while (x <= n and y <= m and a[x][y]
and sum[x][y] - sum[i-1][y] - sum[x][j-1] + sum[i-1][j-1] == tot + 1){
tot++; x++; y++; // && = and 个人习惯
}
当
while (x <= n and y > 0 and a[x][y]
and sum[x][j] - sum[i-1][j] - sum[x][y-1] + sum[i-1][y-1] == tot + 1){
tot++; x++; y--;
}
最后记得保存最大奖品数量。
res = max(res,tot);
恭喜你,完成啦!
(记得 return 0; 哦)
AC Code
#include <bits/stdc++.h>
using namespace std;
const int maxn = 114;
int n,m,a[maxn][maxn],sum[maxn][maxn],res = -1,tot; // res 设为一个小于0的,方便后面max
int main(){
cin >> n >> m;
for (int i = 1;i <= n;i++){
for (int j = 1;j <= m;j++){
cin >> a[i][j];
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i][j];
}
}
//前缀和
if (!sum[n][m]) {cout << 0 << endl; return 0;} // 特判
for (int i = 1;i <= n;i++){
for (int j = 1;j <= m;j++){
if (!a[i][j]) continue; //优化
else {
int x = i,y = j;
while (x <= n and y <= m and a[x][y] and sum[x][y] - sum[i-1][y] - sum[x][j-1] + sum[i-1][j-1] == tot + 1){
tot++; x++; y++;
}
res = max(res,tot);
tot = 0; x = i; y = j;
while (x <= n and y > 0 and a[x][y] and sum[x][j] - sum[i-1][j] - sum[x][y-1] + sum[i-1][y-1] == tot + 1){
tot++; x++; y--;
}
res = max(res,tot);
tot = 0;
}
}
}
cout << res << endl;
return 0;
}
(管理员别卡555)。
第一次写题解,给个赞,谢谢了。