我是靠谱客的博主 感动白开水,这篇文章主要介绍【SJTUOJ笔记】P1074 LSZ的雪地脚印,现在分享给大家,希望可以做个参考。

https://acm.sjtu.edu.cn/OnlineJudge/problem/1074
雪地只有脚印和空白两种状态,可以分别用1和0代表。而查询某一块区域是否可行,就是查询这块区域内所有点的和是否为0,自然用二维前缀和比较合适。
设某一块矩形左上角的坐标为 (i,j) ( i , j ) ,短边长为 k k ,对i,j,k进行枚举,即可得到暴力做法,时间复杂度 O(n3) O ( n 3 )

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
//s是前缀和数组 int ans = 0; for (int i = 1; i <= n; ++i){ for (int j = 1; j <= n; ++j){ int maxlen = min(n - i + 1, (m - j + 1) / 2); // 当前位置的最大可能边长 for (int l = 1; l <= maxlen; ++l){ int x = i + l - 1, y = j + 2 * l - 1; // 右下角坐标 if (s[x][y] - s[i - 1][y] - s[x][j - 1] + s[i - 1][j - 1] == 0){ ans = max(ans, (x - i + 1) * (y - j + 1)); } } } }

但是,这样只能通过 40% 40 % 的数据。
再考虑一下,能否缩小枚举的边长范围。可以发现,若用 f[i,j] f [ i , j ] 表示右下角在 (i,j) ( i , j ) 的最大可行区域的边长, f[i,j] f [ i , j ] 不会超过 f[i1,j]+1 f [ i − 1 , j ] + 1
这里写图片描述
如图,红色部分为右下角在点A的最大可行区域,现在考虑右下角在点B的最大可行区域。若其边长比A大2(黄色部分),则黑框范围同样是右下角在点A的可行区域,矛盾。因此,区域B的边长最多比A大1(橙色部分)。利用这个性质,当整张图中脚印分布较为均匀时,可以大大缩小边长的枚举范围。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//a是原数组,s是前缀和,f如上所述 for (int i = 1; i <= n; ++i){ for (int j = 2; j <= m; ++j){ if (a[i][j]) continue; //此处本身有脚印,不存在可行区域 for (int t = f[i - 1][j] + 1; t >= 1; --t){ //枚举边长 int x = i - t + 1, y = j - 2 * t + 1; //左上角坐标 if (x <= 0 || y <= 0) continue; int p = s[i][j] - s[x - 1][j] - s[i][y - 1] + s[x - 1][y - 1]; if (p == 0){ f[i][j] = t; break; //已经找到了一个解,就无须再考虑边长更小的解了 } } } }

最后

以上就是感动白开水最近收集整理的关于【SJTUOJ笔记】P1074 LSZ的雪地脚印的全部内容,更多相关【SJTUOJ笔记】P1074内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部