[codevs1105][COJ0183][NOIP2005]过河
Posted xjr_01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[codevs1105][COJ0183][NOIP2005]过河相关的知识,希望对你有一定的参考价值。
[codevs1105][COJ0183][NOIP2005]过河
试题描述
题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。
输入
输入第一行有一个正整数L(1<=L<=109),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1<=S<=T<=10,1<=M<=100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。
输出
输入示例
10 2 3 5 2 3 5 6 7
输出示例
2
数据规模及约定
对于30%的数据,L<=10000;
对于全部的数据,L<=109。
题解
L 比较小时,可以直接 dp:设 f(i) 表示到达位置 i 时最少踩过的石子数目。正解与它做法一样,只是发现许多节点是不需要考虑的,所以我们可以忽略它们。暴力找一下 S, T 分别取 1~10 时的最大不可表数,发现只有 71,那么当相邻两个石子间距离超过 71 时,我们就可以将这个距离变成它对 71 取模再加上 2 倍的 71,最后暴力 dp 一下就好了。注意判断 S = T 的情况。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #include <algorithm> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); } return x * f; } #define maxn 27280 int L, S, T, n, A[maxn], f[maxn]; bool has[maxn]; void up(int& a, int b) { if(a < 0) a = b; else a = min(a, b); return ; } int main() { L = read(); S = read(); T = read(); n = read(); for(int i = 1; i <= n; i++) A[i] = read(); sort(A + 1, A + n + 1); if(S == T) { int cnt = 0; for(int i = 1; i <= n; i++) if(A[i] % S == 0) cnt++; return printf("%d\n", cnt), 0; } int p = 0; for(int i = 1; i <= n; i++) if(A[i] - A[i-1] <= 71) p += A[i] - A[i-1], has[p] = 1; else p += (A[i] - A[i-1]) % 71 + 142, has[p] = 1; memset(f, -1, sizeof(f)); f[0] = 0; for(int i = 0; i <= p + 1; i++) if(f[i] >= 0) for(int j = S; j <= T; j++) { int tmp = (i + j <= p + 1) ? i + j : p + 1; up(f[tmp], f[i] + has[tmp]); } printf("%d\n", f[p+1]); return 0; }
以上是关于[codevs1105][COJ0183][NOIP2005]过河的主要内容,如果未能解决你的问题,请参考以下文章
2017.3.11[codevs1937]NOI2010能量采集
多叉树转二叉树+树形dp(codevs 1746 贪吃的九头龙 2002noi)
codevs http://www.codevs.cn/problem/?problemset_id=1 循环递归stl复习题