题目
题意:给定
n
,
m
n,m
n,m,若干个超级点对。从
(
1
,
1
)
(1,1)
(1,1)开始。对于普通点
(
x
,
y
)
(x,y)
(x,y),下一个位置可达
(
x
,
k
)
(x,k)
(x,k)或
(
k
,
y
)
,
k
<
=
x
+
y
(k,y),k<=x+y
(k,y),k<=x+y;对于超级点对
(
x
,
y
)
(x,y)
(x,y),下一个位置可达
(
x
,
k
)
(x,k)
(x,k)或
(
k
,
y
)
(k,y)
(k,y),
k
<
=
x
+
y
+
1
k<=x+y+1
k<=x+y+1。问最少需要多少步,可达
(
n
,
m
)
(n,m)
(n,m)
思路:
1、尽量取最大,不需要取其他数。证明:假设可达
(
x
,
a
)
(x,a)
(x,a)和可达
(
x
,
b
)
,
a
<
b
(x,b),a<b
(x,b),a<b这两个点,那么取
(
x
,
b
)
(x,b)
(x,b)这个点即可,因为
(
x
,
a
)
(x,a)
(x,a)可达的点,
(
x
,
b
)
(x,b)
(x,b)也可达。
2、bfs搜索过程中,对于同一层(即需要相同步数)的点,如果存在
(
x
1
,
y
1
)
,
(
x
,
y
)
(x1,y1),(x,y)
(x1,y1),(x,y),使得
x
1
<
=
x
,
y
1
<
=
y
x1<=x,y1<=y
x1<=x,y1<=y,那么
(
x
1
,
y
1
)
(x1,y1)
(x1,y1)可筛掉,因为
(
x
1
,
y
1
)
(x1,y1)
(x1,y1)可达的点,
(
x
,
y
)
(x,y)
(x,y)也可达,即使
(
x
1
,
y
1
)
(x1,y1)
(x1,y1)是超级点对(因为只加1,可达的范围还是不会超过
(
x
,
y
)
(x,y)
(x,y)的可达范围)。
官方代码
#include<bits/stdc++.h>
using namespace std;
int n, m;
#define x first
#define y second
typedef pair<int, int> comb;
comb norm(const comb& a)
{
return make_pair(min(a.x, n), min(a.y, m));
}
bool good(const comb& a)
{
return a.x == n || a.y == m;
}
bool comp(const comb& a, const comb& b)
{
if(a.x != b.x)
return a.x > b.x;
return a.y > b.y;
}
int main()
{
scanf("%d %d", &n, &m);
int v;
scanf("%d", &v);
set<comb> s;
for(int i = 0; i < v; i++)
{
int x, y;
scanf("%d %d", &x, &y);
s.insert(make_pair(x, y));
}
int steps = 0;
vector<comb> cur;
cur.push_back(make_pair(1, 1));
while(true)
{
if(cur[0] == make_pair(n, m))
break;
vector<comb> ncur;
for(auto x : cur)
{
int sum = x.x + x.y;
if(s.count(x))
sum++;
comb z = x;
z.x = sum;
ncur.push_back(norm(z));
z = x;
z.y = sum;
ncur.push_back(norm(z));
}
sort(ncur.begin(), ncur.end(), comp);
int mx = 0;
vector<comb> ncur2;
for(auto x : ncur)
{
if(x.y <= mx) continue;
mx = max(mx, x.y);
ncur2.push_back(x);
}
cur = ncur2;
steps++;
}
printf("%d\n", steps);
}