1 import java.io.*;
 2 import java.util.*;
 3 
 4 /*
 5 ID: yanglei4
 6 LANG: JAVA
 7 TASK:bigbrn
 8 */
 9 public class bigbrn {
10     public static int min(int a, int b) {
11         if (a < b) return a;
12         else return b;
13     }
14     public static int min3(int a, int b, int c) {
15         return min(a, min(b, c));    
16     }
17     public static void main(String[] args) throws IOException {
18         BufferedReader f = new BufferedReader(new FileReader("bigbrn.in"));
19         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("bigbrn.out")));
20         StringTokenizer st = new StringTokenizer(f.readLine());
21         int N = Integer.parseInt(st.nextToken());
22         int T = Integer.parseInt(st.nextToken());
23         int[][] map = new int[N][N];
24         for (int i = 0; i < T; i++) {
25             st = new StringTokenizer(f.readLine());
26             int x = Integer.parseInt(st.nextToken());
27             int y = Integer.parseInt(st.nextToken());
28             map[x - 1][y - 1= -1;
29         }
30         
31         for (int i = 0; i < N; i++) {
32             if (map[0][i]!= -1)
33                 map[0][i] = 1;
34             if (map[i][0]!= -1)
35                 map[i][0= 1;
36         }
37         
38         
39         for (int i = 1; i < N; i++)
40             for (int j = 1; j < N; j++) {
41                 if (map[i][j] != -1) {
42                     int temp = min3(map[i - 1][j], map[i][j - 1], map[i - 1][j - 1]);
43                     if (temp != -1) map[i][j] = temp + 1;
44                     else map[i][j] = 1;
45                 }
46             }
47         
48         int max = 0;
49         for (int i = 0; i < N; i++)
50             for (int j = 0; j < N; j++)
51                 if (map[i][j] != 0 && map[i][j] > max)
52                     max = map[i][j];
53                 
54         out.println(max);
55         out.close();
56         System.exit(0);
57     }
58 }
59 

应该算是一个比较基本的DP吧,状态转移方程也不难想,但是我最开始写成了N^3的了

首先就是用Map[i][j]来表示以i,j为右下角的最大的square的大小

初始化就是第一行,第一列,如果不是#,那么肯定是1

然后对于i,j,我们需要观察i - 1,j - 1,因为是square,所以只跟这个有关

如果在第i行,第j列上面,从当前位置开始,连续map[i-1][j-1]个位置,没有#的话,那么map[i][j] = map[i-1][j-1]+1

我就是在判断连续map[i-1][j-1]这个地方出了问题,我又加了一层循环,所以就变成了N^3的了,然后果然TLE了

这个地方完全没必要用循环一个一个去判断,因为其实你已经有结果了,这个结果就是map[i-1][j]和map[i][j-1]里面小的那个

map[i-1][j]肯定就是从当前位置开始,在第j列上,向上最多可以走多少步不碰到#

因为这时候实际上你已经确定了,#只有可能出现在第i行,第j列上,因为map[i-1][j-1]不是#就保证了这一点

于是,找到两个方向上走的比较近的那个数,如果这个数是小于map[i-1][j-1]的,那么map[i][j]就等于这个数

否则,map[i][j] = map[i-1][j-1]+1

这个地方的重点就是,如果map[i-1][j-1]不是#,那么就保证了#只能在第i行,第j列上面。

只需要检查这两个就可以

然后我们就可以来看map[i-1][j],map[i][j-1],这两个东西其实跟map[i-1][j-1]共享了上面的一块。

如果在第i行,第j列上面出现了#,那么map[i-1][j],map[i][j-1]肯定比map[i-1][j-1]小

否则,我们的square最大也就只能是map[i-1][j-1]+1,因为map[i-1][j-1]已经是以i-1,j-1为右下角最大的square了

于是状态转移方程就是

map[i][j] = min (map[i-1][j],map[i][j-1],map[i-1][j-1]) + 1, map[i][j] != '#'