Evanyou Blog 彩带

P4753 River Jumping

题目描述

有一条宽度为 NN 的河上,小D位于坐标为 00 的河岸上,他想到达坐标为 NN 的河岸上后再回到坐标为 00 的位置。在到达坐标为 NN 的河岸之前小D只能向坐标更大的位置跳跃,在到达坐标为 NN 的河岸之后小D只能向坐标更小的位置跳跃。在河的中间有 MM 个岩石,小D希望能跳到每个岩石上恰好一次。由于小D的跳跃能力太强,小D的跳跃长度有个下限 SS ,但没有上限。现在请你判断他是否能够完成他的目标。

输入输出格式

输入格式:

 

第一行输入两个整数 N,M,SN,M,S ,分别表示河的宽度,岩石的数量和跳跃长度的下限。

第二行输入 MM 个整数,分别表示 MM 个岩石的坐标 w_1,w_2,\cdots,w_Nw1,w2,,wN 。保证 \{w_i\}{wi} 为递增序列。

 

输出格式:

 

如果小D可以完成他的目标,第一行输出YES,第二行输出 M+2M+2 个数,依次表示小D跳到的石头编号。特殊的,坐标为 00 的河岸编号为 00 ,坐标为 NN 的河岸标号为 M+1M+1 。如果有多种解法,允许输出任意一种。

如果小D不能完成他的目标,第一行输出NO

 

输入输出样例

输入样例#1: 
6 1 3
3
输出样例#1: 
YES
1 2 0
输入样例#2: 
6 2 2
2 4
输出样例#2: 
YES
2 3 1 0
输入样例#3: 
5 2 3
2 3
输出样例#3: 
NO

说明

1 \le N,S \le 1000001N,S100000

0 \le M < N0M<N

1 \le w_i < N1wi<N

 

Solution:

  本题较水,直接贪心。

  每次能跳就跳,打好标记,并记录路径,最后就判断一下标记是否打满,未满就NO,满了就YES并按顺序输出路径经过的点。

代码:

 

#include<bits/stdc++.h>
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
using namespace std;
const int N=100005;
int n,m,s,a[N],vis[N],path[N];

il int gi(){
    int a=0;char x=getchar();
    while(x<'0'||x>'9')x=getchar();
    while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
    return a;
}

int main(){
    n=gi(),m=gi(),s=gi();
    For(i,1,m) a[i]=gi();a[m+1]=n;
    if(a[1]-a[0]<s||a[m+1]-a[m]<s) puts("NO"),exit(0);
    int pos=0,cnt=0;
    For(i,1,m+1) if(!vis[i]&&a[i]-a[pos]>=s) vis[i]=++cnt,pos=i;
    Bor(i,0,m) if(!vis[i]&&a[pos]-a[i]>=s) vis[i]=++cnt,pos=i;
    For(i,0,m+1) {
        if(!vis[i])puts("NO"),exit(0);
        path[vis[i]]=i;
    }
    puts("YES");
    For(i,1,cnt) printf("%d ",path[i]);
    return 0;
}

 

posted @ 2018-07-16 17:56  five20  阅读(101)  评论(0编辑  收藏  举报
Live2D