【解题报告】洛谷 P4753 River Jumping

原题链接

https://www.luogu.com.cn/problem/P4753

题目大意

一条宽度为 nn 的河上,有 mm 块石头,每块石头距离起点(坐标为0)有一个距离,我们要从起点跳到终点,通过一些方法使得跳到每个石头上一次,最终回到起点,每次跳的距离有一个下限 ss ,输出一种可能的方案

思路

看到这道题目,我们首先关注到的是一个下限 ss ,为什么我们要关注这个呢?因为,我们可以发现,如果你想跳的石头与你的距离 dsd \ge s 你是不是就可以随便跳?

于是我们自然而然地想,我们是不是可以使用贪心算法?

每次跳,跳到一个距离自己第一个 s\ge s 的石头上,一直向右,到右边了之后,我们再向左重复上述过程。因为在能完成的情况下我们跳到最右边的时候,离左边的距离一定大于 ss ,所以我们可以跳过去,然后再跳回来,反复横跳,最后就能完成了

那么,我们还要处理不能完成的情况,那么我们什么情况不能完成呢?

  • 最左边的石头和 00 距离小于 ss ,或者最右边的石头和 nn 的距离小于 ss
  • 有连续三个石头之间的距离小于 ss ,因为这样总有一个石头跳不到
  • 00nn 的距离小于 ss ,实际上这个是严格被第一个不能完成的条件包含的

这样,我们找到了所有不能完成的情况

接着,我们进行一个暴力,从 00 开始跳,每次判断是否能跳,如果能跳的话,标记一个 vis=truevis=true 表示已经访问过了,如果已经访问过了,那就访问下一个石头能不能跳.跳到 nn 之后反过来向 00 跳.对于这个过程使用一个 whilewhile 循环就可以了,我们每次循环开头判断一下是否每个石头都走了,如果都走了,那我们退出循环

至于输出的话,一定要记得不要先输出 00 ,它永远都是最后一个,然后我们把输出放在循环里面边跳边输出就可以了

这道题目我昨天干了两个多小时,一直被不能完成的条件所困,请大家一定要注意条件!!!

好的,管理员大大求过

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
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
const int maxn=100005;
int n,m,s;
int w[maxn];
int cnt=0;
bool vis[maxn];
bool flag=false;
bool check()
{
for(int i=0;i<=m+1;i++)
if(!vis[i])
return false;
return true;
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m>>s;

for(int i=1;i<=m;i++)
{
cin>>w[i];
if(w[i]-w[i-1]<s)
cnt++;
else
cnt=0;
if(cnt>=3) flag=true;
}
w[0]=0;w[m+1]=n;

if(n<s)
{
cout<<"NO"<<'\n';
return 0;
}

if(m!=0&&(w[1]<s||n-w[m]<s))
{
cout<<"NO"<<'\n';
return 0;
}
/*if(m==2)
{
if(w[m]-w[m-1]<s)
{
cout<<"NO"<<'\n';
return 0;
}
}*/
if(flag)
{
cout<<"NO"<<'\n';
return 0;
}
cout<<"YES"<<'\n';
int last=0;
int tot=1;
while(!check())
{
for(int i=1;i<=m+1;i++)
{
if(w[i]-w[last]>=s&&!vis[i])
{
cout<<i<<" ";
vis[i]=true;
last=i;
}
else continue;
}
for(int i=last;i>=0;i--)
{
if(w[last]-w[i]>=s&&!vis[i])
{
cout<<i<<" ";
vis[i]=true;
last=i;
}
}
}

return 0;
}