题目大意

  在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点: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. fastjson——json工具库

    fastjson alibaba fastjson是阿里巴巴公司开源维护的一个处理json格式数据的java工具库. 功能特性: 数据绑定databind (json string <--> ...

  2. html——特殊字符

  3. JS——事件基础应用

    直接写在html标签里: <h1 onclick="this.innerHTML='谢谢!'">请点击该文本</h1> 另外一种在脚本里调用: <!D ...

  4. 如何快速获取yun2win app key?

    注册yun2win开发者账号 1.在注册页面输入您的邮箱,点击下方发送,yun2win将会发送一封验证邮件到您的邮箱: 2.如果没有收到邮件请查看垃圾箱或者点击重新发送: 3.打开邮箱查看验证邮件,点 ...

  5. java攻城狮之路--复习JDBC

    1.JDBC中如何获取数据库链接Connection? Driver 是一个接口: 数据库厂商必须提供实现的接口. 能从其中获取数据库连接. 可以通过 Driver 的实现类对象获取数据库连接. 1. ...

  6. CAD插入图块前修改图块文字

    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 3 ...

  7. js基本类型的包装对象

    var test = "test"; test.a = "hello"; console.log(test.a); 在JavaScript中,“一切皆对象”,数 ...

  8. Django - 视图获取请求头

    1.urls.py(url和函数对应关系) 2.通过request.evniron,返回request的所有信息,用索引的方式,获取用户请求头信息. 3.也可以通过key,value方式,来展示请求头 ...

  9. gcc和gdb的基本操作

    gcc和gdb yum 在线安装软件,使用阿里云镜像站,OPSX 选择你安装的系统 点帮助 查看配置命令行 yum --list | grep gdb #查找要安装的软件 yum install -y ...

  10. 37.分组聚合操作—其他metric

    课程大纲     要学其他的metric(count,avg,max,min,sum) count:bucket,terms,自动就会有一个doc_count,就相当于是count avg:avg a ...