zoukankan      html  css  js  c++  java
  • P4753 River Jumping

    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_Nw
    1
    ​ ,w
    2
    ​ ,⋯,w
    N
    ​ 。保证 {w_i}{w
    i
    ​ } 为递增序列。

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

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


    每个点只可能有两种情况被跳到,要么去的时候,要么回的时候。因为腿力巨大,我们当然希望石子挨的越远越好。

    这样就有了贪心的基本思路:在第一次去的时候尽量跳多的点,“尽可能为第二次跳删去多的点”

    所以说纠正一些题解的讲法:这题不全是贪心,前一次跳为贪心,删去尽可能多的点,而第二次仅仅是一个判断,因为若是不满足条件,那么这个点再没有第三次机会被删去了

    注意样例是把两岸当做点处理的

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    typedef long long LL;
    using namespace std;
    int RD(){
        int out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const int maxn = 100019;
    int len, num, S;
    int a[maxn];
    bool vis[maxn];
    int pre[maxn];
    int s[maxn],top;
    int main(){
    	len = RD();num = RD();S = RD();
    	for(int i = 1;i <= num;i++){a[i] = RD();}
    	a[0] = 0, a[num + 1] = len;
    	int i = 1,now = 0,tot = num, last = 0;
    	while(i <= num){
    		if(now + S <= a[i])tot--, pre[i] = last, last = i, now = a[i], vis[i] = 1;
    		i++;
    		}
    	if(a[last] + S > len){printf("NO
    ");return 0;}
    	pre[num + 1] = last;
    	i = num, now = len, last = num + 1;
    	while(i >= 1){
    		if(now - S >= a[i] && !vis[i])tot--, pre[i] = last, last = i, now = a[i], vis[i] = 1;
    		i--;
    		}
    	if(a[last] - S < 0){printf("NO
    ");return 0;}
    	if(!tot){
    		printf("YES
    ");
    		while(pre[last] != 0)s[++top] = last, last = pre[last];
    		s[++top] = last;
    		while(top)printf("%d ", s[top--]);
    		printf("0
    ");
    		}
    	else printf("NO
    ");
    	return 0;
    	}
    
  • 相关阅读:
    C#分部类和分部方法的使用
    C# 关于线程锁lock的使用方法
    Halcon标定流程及注意事项
    C#如何将ListView中的数据导出到Excel中
    Application.DoEvents()的作用
    (C#)使用队列(Queue)解决简单的并发问题
    C#的委托 VS C++的指针
    转载——卷积神经网络(CNN)基础入门介绍
    Linux启动详细过程(开机启动顺序)
    Nginx https 证书配置
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9315614.html
Copyright © 2011-2022 走看看