题目大意

  在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

思路

  本题动规不用说,问题在于怎么使路径压缩。

思路1

  求出一个单位长度$x$,使得青蛙在区间$[1,x]$上从$[1,T]$开始起跳时,总会有一种跳法跳到$x$处。更严谨地说,也就是存在一个序列$K$,使得$x=\sum_{i=S}^T iK_i$。我们看看$S,T$取值范围,简单粗暴地想,令$K_i=\gcd(1,2,\cdots i-1, i+1, \cdots 10)$即可。也就是说,$x=\mathrm{lcm}(1, 2, \cdots, 10)$。所以对每一个间隔模个$x$即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAX_LEN = 2100 * 100, MAX_STONE_CNT = 110, Unit = 2050, INF = 0x3f3f3f3f;
int Delta[MAX_STONE_CNT], F[MAX_LEN], A[MAX_STONE_CNT];
bool HaveStone[MAX_LEN];
int Len, S, T, TotStone; int main()
{
scanf("%d%d%d%d", &Len, &S, &T, &TotStone);
for (int i = 1; i <= TotStone; i++)
scanf("%d", A + i);
sort(A + 1, A + TotStone + 1);
if (S == T)
{
int ans = 0;
for (int i = 1; i <= TotStone; i++)
ans += (A[i] % T == 0);
printf("%d\n", ans);
return 0;
}
for (int i = 1; i <= TotStone; i++)
{
Delta[i] = A[i] - A[i - 1];
}
Delta[TotStone + 1] = Len - A[TotStone];
for (int i = 1; i <= TotStone + 1; i++)
Delta[i] %= Unit;
int prevP = 0;
for (int i = 1; i <= TotStone; i++)
HaveStone[prevP += Delta[i]] = true;
Len = prevP + Delta[TotStone + 1];
memset(F, INF, sizeof(F));
F[0] = 0;
for (int i = 1; i <= Len; i++)
for (int j = S; j <= T && j <= i; j++)
F[i] = min(F[i], F[i - j] + HaveStone[i]);
int ans = INF;
for (int i = Len - T; i <= Len; i++)
ans = min(ans, F[i]);
printf("%d\n", ans);
return 0;
}

思路二

  求一个区间长度,使得任何大于这个区间长度的位置都可以到达。我们做过《小凯的疑惑》,知道对任意两个互质的数$a,b$,若整数$x>ab$,则总存在整数$k,t$,使得$x=ka+tb$。因为$t, t-1$互质,所以任何大于$t(t-1)$的位置都可到达。所以遇到大于$t(t-1)$的间隔便将其改为$t(t-1)$即可达到压缩效果。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAX_LEN = 2100 * 100, MAX_STONE_CNT = 110, INF = 0x3f3f3f3f;
int A[MAX_STONE_CNT], Delta[MAX_STONE_CNT], F[MAX_LEN];
bool HaveStone[MAX_LEN];
int Len, S, T, TotStone, Unit; int main()
{
scanf("%d%d%d%d", &Len, &S, &T, &TotStone);
Unit = T * (T - 1);
for (int i = 1; i <= TotStone; i++)
scanf("%d", A + i);
sort(A + 1, A + TotStone + 1);
if (S == T)
{
int ans = 0;
for (int i = 1; i <= TotStone; i++)
ans += (A[i] % T == 0);
printf("%d\n", ans);
return 0;
}
for (int i = 1; i <= TotStone; i++)
{
Delta[i] = A[i] - A[i - 1];
}
Delta[TotStone + 1] = Len - A[TotStone];
for (int i = 1; i <= TotStone + 1; i++)
if (Delta[i] > Unit)
Delta[i] = Unit;
int prevP = 0;
for (int i = 1; i <= TotStone; i++)
HaveStone[prevP += Delta[i]] = true;
Len = prevP + Delta[TotStone + 1];
memset(F, INF, sizeof(F));
F[0] = 0;
for (int i = 1; i <= Len; i++)
for (int j = S; j <= T && j <= i; j++)
F[i] = min(F[i], F[i - j] + HaveStone[i]);
int ans = INF;
for (int i = Len - T; i <= Len; i++)
ans = min(ans, F[i]);
printf("%d\n", ans);
return 0;
}

  

luogu1052 过河的更多相关文章

  1. [LeetCode] Frog Jump 青蛙过河

    A frog is crossing a river. The river is divided into x units and at each unit there may or may not ...

  2. [codevs1105][COJ0183][NOIP2005]过河

    [codevs1105][COJ0183][NOIP2005]过河 试题描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青 ...

  3. A*算法 -- 八数码问题和传教士过河问题的代码实现

    前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...

  4. 袋鼠过河---DP

    题目:一只袋鼠要从河这边跳到河对岸,河很宽,但是河中间打了很多桩子,每隔一米就有一个,每个桩子上都有一个弹簧,袋鼠跳到弹簧上就可以跳的更远,每个弹簧力量不同,用一个数字代表它的力量,如果弹簧力量为5, ...

  5. NOIP2005过河[DP 状态压缩]

    题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数 ...

  6. ACM 过河问题

    过河问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:5   描述 在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边.如果不借助手电筒的话,大家是无论如何也不敢过桥去的 ...

  7. NOIP 2005 青蛙过河

    做题记录:2016-08-10 21:58:09 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都 ...

  8. 过河问题nyoj47

    时间限制:1000 ms  |  内存限制:65535 KB 难度:5   描述 在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边.如果不借助手电筒的话,大家是无论如何也不敢过桥去的.不幸的是 ...

  9. 商人过河问题(DFS)

    问题描述:3个商人带着3个仆人过河,过河的工具只有一艘小船,只能同时载两个人过河,包括划船的人.在河的任何一边,只要仆人的数量超过商人的数量,仆人就会联合起来将商人杀死并抢夺其财物,问商人应如何设计过 ...

随机推荐

  1. 您厉害您赚得多:聪明投资者的聊天记录,雪球CEO的21条投资理念

    3星|<您厉害您赚得多>:雪球创始人的投资理念.原则.技巧,及其在雪球上跟一些用户的互动的内容 作者是雪球创始人.CEO,全书基本是作者的一些投资理念+作者在雪球上跟用户的互动的内容,还有 ...

  2. linux 汇编 - 函数调用

    Linux 汇编-函数调用 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !i ...

  3. 关于Python中的classmethod

    Python 中的 classmethod classmethod: 作用是直接将自己的类对象,传给类方法. 一.classmethod 1)不用classmethod的时候 你的代码可能是这样写的, ...

  4. Mysql 之show status数据详解

    状态名 作用域 详细解释 Aborted_clients Global 由于客户端没有正确关闭连接导致客户端终止而中断的连接数 Aborted_connects Global 试图连接到MySQL服务 ...

  5. requirejs(模块化)

    <script src="../../dist/js/require.js" data-main="../../dist/js/main.js">& ...

  6. MySQL中的分页操作结合python

    mysql中的分页操作结合python --分页: --方式1: ;-- 读取十行 , --从第十行读取 往后再读十行 --方式2: offset ; --从第二十行开始读取10行 -- 结合pyth ...

  7. Huawei-R&S-网络工程师实验笔记20190609-VLAN划分综合(Access和Trunk端口)

    >Huawei-R&S-网络工程师实验笔记20190609-VLAN划分综合(Access和Trunk端口) >>实验开始,先上拓扑图参考: >>>实验目标 ...

  8. asciiflow

    http://asciiflow.com/ https://maxiang.io/# http://www.jianshu.com/p/19432b5e3c60

  9. iOS:让64位兼容百度地图

    当使用了百度地图sdk的app在64位机中运行时,会出现No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_6 ...

  10. Openfire:重新配置openfire

    有些时候当我们在对openfire开发时,需要重置openfire的配置,这时最简单的方法就是重新运行openfire的安装程序.要重新运行安装程序,方法很简单: 打开openfire的安装目录,找到 ...