题意大致是这样的:有一个有n行、每行m个格子的矩形,每次往指定格子里填石子,如果指定格子里已经填过了,则找到与其曼哈顿距离最小的格子,然后填进去,有多个的时候依次按x、y从小到大排序然后取最小的。输出每次填的格子的坐标。
思路:这道题出自Codeforces Round #126 (Div. 2)是个暴力优化的题。如果指定格子未填,则填到里面。否则枚举曼哈顿距离,然后枚举格子找答案。裸的暴力太慢了,主要是因为每次曼哈顿距离都是从1开始搜索,如果每次指定的坐标都是同一个,则做了大量的重复工作。不妨用一个数组r[x][y]表示与(x,y)这个格子曼哈顿距离不超过r[x][y]的格子全部被填过了。r数组满足这样一个关系,r[x][y]>=r[x'][y']-dist{(x,y),(x',y')},每次使用r[x][y]之前,用(x,y)周围的一些点更新下就行了。复杂度比较模糊,必须承认,这种优化简直太神,对于极端数据和随机数据都灰常之快
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
/* ******************************************************************************** */
#include <iostream> //
#include <cstdio> //
#include <cmath> //
#include <cstdlib> //
#include <cstring> //
#include <vector> //
#include <ctime> //
#include <deque> //
#include <queue> //
#include <algorithm> //
#include <map> //
#include <cmath> //
using
namespace
std;
//
//
#define pb push_back //
#define mp make_pair //
#define X first //
#define Y second //
#define all(a) (a).begin(), (a).end() //
#define fillchar(a, x) memset(a, x, sizeof(a)) //
//
typedef
pair<
int
,
int
> pii;
//
typedef
long
long
ll;
//
typedef
unsigned
long
long
ull;
//
//
#ifndef ONLINE_JUDGE //
void
RI(vector<
int
>&a,
int
n){a.resize(n);
for
(
int
i=0;i<n;i++)
scanf
(
"%d"
,&a[i]);}
//
void
RI(){}
void
RI(
int
&X){
scanf
(
"%d"
,&X);}
template
<
typename
...R>
//
void
RI(
int
&f,R&...r){RI(f);RI(r...);}
void
RI(
int
*p,
int
*q){
int
d=p<q?1:-1;
//
while
(p!=q){
scanf
(
"%d"
,p);p+=d;}}
void
print(){cout<<endl;}
template
<
typename
T>
//
void
print(
const
T t){cout<<t<<endl;}
template
<
typename
F,
typename
...R>
//
void
print(
const
F f,
const
R...r){cout<<f<<
", "
;print(r...);}
template
<
typename
T>
//
void
print(T*p, T*q){
int
d=p<q?1:-1;
while
(p!=q){cout<<*p<<
", "
;p+=d;}cout<<endl;}
//
#endif // ONLINE_JUDGE //
template
<
typename
T>
bool
umax(T&a,
const
T&b){
return
b<=a?
false
:(a=b,
true
);}
//
template
<
typename
T>
bool
umin(T&a,
const
T&b){
return
b>=a?
false
:(a=b,
true
);}
//
template
<
typename
T>
//
void
V2A(T a[],
const
vector<T>&b){
for
(
int
i=0;i<b.size();i++)a[i]=b[i];}
//
template
<
typename
T>
//
void
A2V(vector<T>&a,
const
T b[]){
for
(
int
i=0;i<a.size();i++)a[i]=b[i];}
//
//
const
double
PI =
acos
(-1.0);
//
const
int
INF = 1e9 + 7;
//
//
/* -------------------------------------------------------------------------------- */
const
int
maxn = 2e3 + 7;
bool
plot[maxn][maxn];
int
r[maxn][maxn];
int
n, m, k;
int
check(
int
row,
int
col) {
if
(col >= 0 && col < m)
return
true
;
return
false
;
}
int
main() {
#ifndef ONLINE_JUDGE
freopen
(
"in.txt"
,
"r"
, stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
cin >> n >> m >> k;
for
(
int
i = 0; i < k; i ++) {
int
x, y;
scanf
(
"%d%d"
, &x, &y);
x --; y --;
if
(!plot[x][y]) {
printf
(
"%d %d\n"
, x + 1, y + 1);
plot[x][y] =
true
;
continue
;
}
for
(
int
d = 1; d <= 3; d ++) {
int
Max = min(n, x + d + 1);
for
(
int
row = max(0, x - d); row < Max; row ++) {
int
t = d -
abs
(x - row), col1 = y - t, col2 = y + t;
if
(check(row, col1)) umax(r[x][y], r[row][col1] - d);
if
(check(row, col2)) umax(r[x][y], r[row][col2] - d);
}
}
for
(
int
d = r[x][y] + 1; ; d ++) {
int
Max = min(n, x + d + 1);
bool
ok =
false
;
for
(
int
row = max(0, x - d); row < Max; row ++) {
int
t = d -
abs
(x - row), col1 = y - t, col2 = y + t;
if
(check(row, col1) && !plot[row][col1]) {
ok =
true
;
printf
(
"%d %d\n"
, row + 1, col1 + 1);
plot[row][col1] =
true
;
break
;
}
if
(check(row, col2) && !plot[row][col2]) {
ok =
true
;
printf
(
"%d %d\n"
, row + 1, col2 + 1);
plot[row][col2] =
true
;
break
;
}
}
if
(ok) {
r[x][y] = d - 1;
break
;
}
}
}
return
0;
}
/* ******************************************************************************** */
|