题意
给出
n
n
n根柱子,每根柱在
0
0
0时刻沉下去,然后有
a
a
a个时间单元浮上来,
b
b
b个时间单元沉下去,再有
a
a
a个时间单元浮上来,
b
b
b个时间单元沉下去,等等。
在
t
+
1
t+1
t+1时刻,市民可以选择距离t时刻所在位置
5
5
5根柱子之内的可靠的柱子上﹑岸上,或者站在当前的柱子上(如果可靠)或岸上。
求出最短的过河时间,如果不能过输出
N
o
No
No。
思路
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]为第
i
i
i个单位时间时,
j
j
j这个点是否能到达,可得:
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
−
5
]
∣
f
[
i
−
1
]
[
j
−
4
]
…
…
f
[
i
]
[
j
+
5
]
f[i][j]=f[i-1][j-5]|f[i-1][j-4]……f[i][j+5]
f[i][j]=f[i−1][j−5]∣f[i−1][j−4]……f[i][j+5]
由于不知道需要多少时间,所以我们可以根据数据算出来范围大约是
800
800
800。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
int x, n;
int a[1001], b[1001], f[2][1006];
int main() {
scanf("%d", &x);
while (x--) {
int flag = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d %d", &a[i], &b[i]);
memset(f, 0, sizeof(f));
for (int ans = 1; ans <= 800; ans++) {
memset(f[ans & 1], 0, sizeof(f[ans & 1]));
f[!(ans & 1)][0] = 1;
for (int i = 1; i <= n; i++) {
if ((ans - 1) % (a[i] + b[i]) + 1 > a[i]) f[ans & 1][i] = 0;
else {
int l = std::max(0, i - 5);
for (int j = l; j <= i + 5; j++)
f[ans & 1][i] |= f[!(ans & 1)][j];
}
}
for (int i = 0; i <= 5; i++)
flag |= f[ans & 1][n - i + 1];
if (flag) {
printf("%d\n", ans + 1);
break;
}
}
if (!flag) printf("No\n");
}
}