题目链接:

http://codeforces.com/contest/435/problem/D

D. Special Grid

time limit per test:4 seconds
memory limit per test:256 megabytes
#### 问题描述
> You are given an n × m grid, some of its nodes are black, the others are white. Moreover, it's not an ordinary grid — each unit square of the grid has painted diagonals.
>
> The figure below is an example of such grid of size 3 × 5. Four nodes of this grid are black, the other 11 nodes are white.
>
>
> Your task is to count the number of such triangles on the given grid that:
>
> the corners match the white nodes, and the area is positive;
> all sides go along the grid lines (horizontal, vertical or diagonal);
> no side contains black nodes.
#### 输入
> The first line contains two integers n and m (2 ≤ n, m ≤ 400). Each of the following n lines contain m characters (zeros and ones) — the description of the grid. If the j-th character in the i-th line equals zero, then the node on the i-th horizontal line and on the j-th vertical line is painted white. Otherwise, the node is painted black.
>
> The horizontal lines are numbered starting from one from top to bottom, the vertical lines are numbered starting from one from left to right.

输出

Print a single integer — the number of required triangles.

样例

sample input

3 5

10000

10010

00001

sample output

20

题意

给你一个网格(网格有对角线),问由网格的边和对角线构成的三角形(三条边上都不能有任何黑点)个数。

题解

其实满足要求的三角形只有等腰直角三角形

对每个点,我们先预处理出八个方向能延伸出去的最大长度。(预处理出来这些,我们就可以判断一个直角三角形的三条边上是否有黑点了。比如对于三角形0 + 3 的斜边,你只要考虑0的左上角能延伸的最大长度或者3的右下角能延伸的最大长度就可以了)

然后枚举每个点,统计以这个点为直角的所有三角形的个数

对8个方向做一个说明:
7 3 4
\ | /
\ | /
\|/
2---+---0
/|\
/ | \
/ | \
6 1 5 八个方向组成的以'+'为原点,长度为1的直角:
0 -> + -> 1
+-
| 1 -> + -> 2
-+
| 2 -> + -> 3
|
-+ 3 -> + -> 0
|
+- 4 -> + -> 5
/
+
\ 5 -> + -> 6
+
/ \ 6 -> + -> 7
\
+
/ 7 -> + -> 4
\ /
+

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int maxn = 444; char str[maxn][maxn]; //dp[i][j][d]记录(i,j)顶点从八个方向扩散出去的长度(这里的长度是按顶点数来度量的)。
int dp[maxn][maxn][8]; typedef __int64 LL; int n, m; int main() {
scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%s", str[i] + 1); for (int i = 0; i < maxn; i++) str[i][0] = str[0][i] = str[n + 1][i] = str[i][m + 1] = '1'; for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
//预处理出每个顶点八个方向能延伸出去的最大长度
for (int k = 0;; k++) if (str[i][j + k] == '1') {
dp[i][j][0] = k - 1; break;
}
for (int k = 0;; k++) if (str[i + k][j] == '1') {
dp[i][j][1] = k - 1; break;
}
for (int k = 0;; k++) if (str[i][j - k] == '1') {
dp[i][j][2] = k - 1; break;
}
for (int k = 0;; k++) if (str[i - k][j] == '1') {
dp[i][j][3] = k - 1; break;
}
for (int k = 0;; k++) if (str[i - k][j + k] == '1') {
dp[i][j][4] = k - 1; break;
}
for (int k = 0;; k++) if (str[i + k][j + k] == '1') {
dp[i][j][5] = k - 1; break;
}
for (int k = 0;; k++) if (str[i + k][j - k] == '1') {
dp[i][j][6] = k - 1; break;
}
for (int k = 0;; k++) if (str[i - k][j - k] == '1') {
dp[i][j][7] = k - 1; break;
}
}
} int ma = max(n, m);
LL ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int cnt = ans;
//这里的k可以理解为两直角边的长度。
for (int k = 1; k <= ma; k++) {
//计算以(i,j)这个顶点为直角的等腰直角三角形(总共有八个,看几个是合法的) //这四种情况中直角由网格的两条邻边构成
//这四种情况等腰直角三角形三边跨越的顶点数刚好都是相等的
if (k <= dp[i][j][0] && k <= dp[i][j][1] && k <= dp[i][j + k][6]) {
ans++;
}
if (k <= dp[i][j][1] && k <= dp[i][j][2] && k <= dp[i + k][j][7]) {
ans++;
}
if (k <= dp[i][j][2] && k <= dp[i][j][3] && k <= dp[i][j - k][4]) {
ans++;
}
if (k <= dp[i][j][3] && k <= dp[i][j][0] && k <= dp[i - k][j][5]) {
ans++;
} //这四种情况中直角由网格的两条相邻对角线构成
//这里开始斜边跨越的节点数刚好是直角边的两倍,所以斜边是2*k。
if (k <= dp[i][j][4] && k <= dp[i][j][5] && 2*k <= dp[i - k][j + k][1]) {
ans++;
}
if (k <= dp[i][j][5] && k <= dp[i][j][6] && 2*k <= dp[i + k][j + k][2]) {
ans++;
}
if (k <= dp[i][j][6] && k <= dp[i][j][7] && 2*k <= dp[i + k][j - k][3]) {
ans++;
}
if (k <= dp[i][j][7] && k <= dp[i][j][4] && 2*k <= dp[i - k][j - k][0]) {
ans++;
}
}
}
}
printf("%I64d\n", ans);
return 0;
} /*
3 3
001
010
000 3 4
0010
0100
0010 5 5
00000
01010
00000
01010
00000 4 4
0000
0111
0011
0111
*/

Codeforces Round #249 (Div. 2) D. Special Grid 枚举的更多相关文章

  1. 模拟 Codeforces Round #249 (Div. 2) C. Cardiogram

    题目地址:http://codeforces.com/contest/435/problem/C /* 题意:给一组公式,一组数据,计算得到一系列的坐标点,画出折线图:) 模拟题:蛮恶心的,不过也简单 ...

  2. 构造 Codeforces Round #135 (Div. 2) B. Special Offer! Super Price 999 Bourles!

    题目传送门 /* 构造:从大到小构造,每一次都把最后不是9的变为9,p - p MOD 10^k - 1,直到小于最小值. 另外,最多len-1次循环 */ #include <cstdio&g ...

  3. Codeforces Round #249 (Div. 2) C题,模拟画图 ----未解决!

    http://codeforces.com/contest/435/problem/C

  4. Codeforces Round #249 (Div. 2)B(贪心法)

    B. Pasha Maximizes time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  5. Codeforces Round #249 (Div. 2) A题

    链接:http://codeforces.com/contest/435/problem/A   A. Queue on Bus Stop time limit per test 1 second m ...

  6. Codeforces Round #249 (Div. 2)

    A.水题. #include <cstdio> #include <iostream> #include <cstdlib> #include <cstrin ...

  7. Codeforces Round #249 (Div. 2) 总结

    D.E还是很难的.....C不想多说什么... A:提意:给出每一组人的个数,以及一次车载容量,求出最少需要多少次才能载走所有的人. water: http://codeforces.com/cont ...

  8. Codeforces Round #249 (Div. 2) (模拟)

    C. Cardiogram time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  9. Codeforces Round #249 (Div. 2) C. Cardiogram

    C. Cardiogram time limit per test 1 second memory limit per test 256 megabytes input standard input ...

随机推荐

  1. Vue.js学习 Item1 --快速入门

    我们以 Vue 数据绑定的快速导览开始.如果你对高级概述更感兴趣,可查看这篇博文. 尝试 Vue.js 最简单的方法是使用 JSFiddle Hello World 例子.在浏览器新标签页中打开它,跟 ...

  2. canvas 绘圆加边框

    HTML5中canvas元素,绘制圆形需要使用路径,开始时要取得图形上下文,首先使用路径来勾勒图形的轮廓,然后设置颜色,进行绘制. arc(cx,cy,radius,start_angle,end_a ...

  3. KMP串匹配算法解析与优化

    朴素串匹配算法说明 串匹配算法最常用的情形是从一篇文档中查找指定文本.需要查找的文本叫做模式串,需要从中查找模式串的串暂且叫做查找串吧. 为了更好理解KMP算法,我们先这样看待一下朴素匹配算法吧.朴素 ...

  4. 【转】 BSS段 数据段 代码段 堆栈 指针 vs 引用

    原文:http://blog.csdn.net/godspirits/article/details/2953721 BSS段 数据段 代码段 堆栈 (转+) 声明:大部分来自于维基百科,自由的百科全 ...

  5. IL中的栈和闪电的Owin推荐

    最近几天有幸得到闪电大哥的指点,了解了EMIT和IL中的一些指令.虽然有高射炮打蚊子的说法,但是我相信“二八定律”,80%的功能可以用20%的技术解决,20%的功能只能用80%的技术解决.大哥的博客: ...

  6. book publisher and study

    http://www.apress.com/ https://pragprog.com/ https://www.packtpub.com/ http://www.howzhi.com/

  7. 编译mgiza的准备

    cmake之前需要首先设置环境变量: export BOOST_LIBRARYDIR=$BOOST_ROOT/lib64export BOOST_ROOT=/home/noah/boost_1_57_ ...

  8. [笔记]--Oracle修改SGA大小

    1.通过spfile修改 (1)使用SYS用户以SYSDBA身份登录系统 (2)查看修改前sga_max_size,sga_target大小 show parameter sga_max_size; ...

  9. NOJ1066-堆排序

    堆排序 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 414            测试通过 : 220  比 ...

  10. 做HDU1010 带出来一个小问题

    做1010  本来是想的DFS深搜  但是自己凭空打  打不出来  因为没有记模板  然后就去搜  但是看了一遍  自己打却又是有BUG  然后验证  就出现了一个二维字符数组打印的问题 开始代码是这 ...