Alpha Centauri-M (ACM) is a planet with marvelous scenes for visitors from the Earth. Luckily you win a ticket to participate in a space tour to Alpha Centauri-M.
The map of the planet ACM is divided into a grid of M rows andN columns. The columns are indexed from 1 toN (from left to right) and the rows are indexed from 1 toM (from top to bottom). There are several cells on the map that are not safe for visitors to explore because of high mountains and volcanoes.
Upon arriving at ACM, the spaceship will land on any safe cell on the grid and passengers can visit the planet via a special system of space cars. From the landing cell(r0, c0) on the map, a space car can go to either one of the four connected adjacent cells, namely(r0–1, c0), (r0 + 1, c0), (r0, c0–1), (r0, c0 + 1). Subsequently, the space car will continue moving the following fixed navigation pattern:
- Turn right and go forward one cell
- Turn left and go forward one cell
- Go back to step 1.
A space car can only visit safe cells, therefore it will stop if the next cell is not safe or is beyond the map boundaries. The following figure illustrates a map consisting ofM = 6 rows and N = 7 columns. From the landing cell(4, 3), you may visit 16 cells (including the landing cell).
For each landing cell on the map, you can determine the number of cells that you can visit (including the landing cell). Your task is to choose the landing cell from which you can visit the maximum number of cells on Alpha Centauri-M.
The input file consists of several datasets. The first line of the input file contains the number of datasets which is a positive integer and is not greater than 20. The following lines describe the datasets.
The first line of a dataset contains 2 space-separated positive integers M and N (1 ≤ M, N ≤ 1000). The ith line in the nextM lines of the dataset contains N binary digits to represent the states of all cells in the ith row of the map (1: safe cell, 0: unsafe cell).
For each dataset, write in one line the maximum number of cells that you can visit on Alpha Centauri-M (including the landing cell).
2 3 3 011 111 111 6 7 1101011 0111111 1111101 1111111 1111110 0111111
8
20
题意:给你一个 M * N 的迷宫,‘1’代表可行点,‘0’代表不可行点。从起点出发,可以沿四条路线行走:(1)up -> right -> up -> right -> ...... (2)right -> down -> right -> down -> ...... (3) down -> left -> down -> left -> ...... (4)left -> up -> left -> up -> ...... 可得到从起点开始能走的点的总和。现在要你确定一个起点,使得所能走的点的总和最大。
分析:预处理 + 枚举。一开始看题还以为是搜索,后来看看数据有点大所以肯定不是这个方向。再看看图,其实还是蛮有规律的,比如按照第一条路线行走时,假设起点是(sx, sy),那么行走的点肯定都在以(sx, sy)、(sx - 1, sy)为端点、右斜上方45度的射线上,可行点即为从(sx, sy)、(sx -1, sy) 出发沿射线线无障碍的可行的最远处(分别假设可行点的个数为num1,num2),那么,当 num1 <= num2 时,除去起点外,总点数为 2 * num1 - 1,否则为 2 * num2。依次类推,四个方向都是这个规则。所以,关键在于预处理出每个点的四个方向的可行点数,然后依次枚举每一个起点,取最大值。
题目链接: http://codeforces.com/gym/100541/problem/I
代码清单(有点挫,不忍直视):
/*******************************************************************************
*** problem ID : I_Space_Tour.cpp
*** create time : Sun Nov 01 09:42:31 2015
*** author name : nndxy
*** author blog : http://blog.csdn.net/jhgkjhg_ugtdk77
*** author motto: never loose enthusiasm for life, life is to keep on fighting!
*******************************************************************************/
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <vector>
#include <cctype>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
#define end() return 0
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
const int maxn = 1000 + 5;
int T;
int M, N;
char str[maxn][maxn];
int length[maxn][maxn][5];
void input(){
memset(str, '\0', sizeof(str));
scanf("%d%d", &M, &N);
for(int i = 0; i < M; i++){
scanf("%s", str[i]);
}
}
bool check(int x, int y) { return (x >= 0 && x < M && y >= 0 && y < N); }
void initAns(){
memset(length, 0, sizeof(length));
int sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3;
for(int i = 0; i < N; i++){
sx0 = 0; sy0 = i;
while(check(sx0, sy0)){
if(sx0 == 0){
if(str[sx0][sy0] == '1') length[sx0][sy0][0] = 1;
}
else if(str[sx0][sy0] == '1') length[sx0][sy0][0] = length[sx0 - 1][sy0 - 1][0] + 1;
sx0++; sy0++;
}
sx1 = 0; sy1 = i;
while(check(sx1, sy1)){
if(sx1 == 0){
if(str[sx1][sy1] == '1') length[sx1][sy1][1] = 1;
}
else if(str[sx1][sy1] == '1') length[sx1][sy1][1] = length[sx1 - 1][sy1 + 1][1] + 1;
sx1++; sy1--;
}
sx2 = M - 1; sy2 = i;
while(check(sx2, sy2)){
if(sx2 == M - 1){
if(str[sx2][sy2] == '1') length[sx2][sy2][2] = 1;
}
else if(str[sx2][sy2] == '1') length[sx2][sy2][2] = length[sx2 + 1][sy2 + 1][2] + 1;
sx2--; sy2--;
}
sx3 = M - 1; sy3 = i;
while(check(sx3, sy3)){
if(sx3 == M - 1){
if(str[sx3][sy3] == '1') length[sx3][sy3][3] = 1;
}
else if(str[sx3][sy3] == '1') length[sx3][sy3][3] = length[sx3 + 1][sy3 - 1][3] + 1;
sx3--; sy3++;
}
}
for(int i = 0; i < M; i++){
sx0 = i; sy0 = 0;
while(check(sx0, sy0)){
if(sy0 == 0){
if(str[sx0][sy0] == '1') length[sx0][sy0][0] = 1;
}
else if(str[sx0][sy0] == '1') length[sx0][sy0][0] = length[sx0 - 1][sy0 - 1][0] + 1;
sx0++; sy0++;
}
sx1 = i; sy1 = N - 1;
while(check(sx1, sy1)){
if(sy1 == N - 1){
if(str[sx1][sy1] == '1') length[sx1][sy1][1] = 1;
}
else if(str[sx1][sy1] == '1') length[sx1][sy1][1] = length[sx1 - 1][sy1 + 1][1] + 1;
sx1++; sy1--;
}
sx2 = i; sy2 = N - 1;
while(check(sx2, sy2)){
if(sx2 == N - 1){
if(str[sx2][sy2] == '1') length[sx2][sy2][2] = 1;
}
else if(str[sx2][sy2] == '1') length[sx2][sy2][2] = length[sx2 + 1][sy2 + 1][2] + 1;
sx2--; sy2--;
}
sx3 = i; sy3 = 0;
while(check(sx3, sy3)){
if(sy3 == 0){
if(str[sx3][sy3] == '1') length[sx3][sy3][3] = 1;
}
else if(str[sx3][sy3] == '1') length[sx3][sy3][3] = length[sx3 + 1][sy3 - 1][3] + 1;
sx3--; sy3++;
}
}
}
void solve(){
initAns();
int ans = 0;
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
if(str[i][j] == '0') continue;
int sum = 1;
if(i - 1 >= 0){
if(length[i - 1][j][1] < length[i][j][1]){
sum += 2 * length[i - 1][j][1];
}
else{
sum += 2 * length[i][j][1] - 1;
}
}
if(i + 1 < M){
if(length[i + 1][j][3] < length[i][j][3]){
sum += 2 * length[i + 1][j][3];
}
else{
sum += 2 * length[i][j][3] - 1;
}
}
if(j - 1 >= 0){
if(length[i][j - 1][0] < length[i][j][0]){
sum += 2 * length[i][j - 1][0];
}
else{
sum += 2 * length[i][j][0] - 1;
}
}
if(j + 1 < N){
if(length[i][j + 1][2] < length[i][j][2]){
sum += 2 * length[i][j + 1][2];
}
else{
sum += 2 * length[i][j][2] - 1;
}
}
ans = max(ans, sum);
}
}
printf("%d\n", ans);
}
int main(){
scanf("%d", &T);
while(T--){
input();
solve();
} end();
}