题目大意

  在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点: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. Android 在fragment中实现返回键单击提醒 双击退出

    尝试用mvp架构加dagger2来重写了一下,大致功能都实现了,还没有全部完成. 项目地址 接近完成的时候,想在天气信息页面实现一个很常见的功能,也就是点击屏幕下方的返回键的时候不是返回到上一个act ...

  2. 如何用java生成随机验证码

     1.VerifyCode 类:   1 package com.HRuinger.enity;                          ImageIO.write(image, " ...

  3. R语言数据重塑

    使用cbind()函数连接多个向量来创建数据帧.此外,使用rbind()函数合并两个数据帧   使用merge()函数合并两个数据帧.数据帧必须具有相同的列名称,在其上进行合并   melt()拆分数 ...

  4. windows程序设为开机自启动

    在Windows文件管理器中输入 %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup 把程序快捷方式放到此处即可.

  5. Eclipse 使用前的配置

    一,修改eclipse对jdk的依赖项 1.查看设置的编译器编译版本:设置成本地jdk一致的版本 点击窗口->首选项 找到java 选择编辑器,查看现在的编译jdk版本 改成本地jdk版本 jd ...

  6. golang实现高阶函数之map

    package main import "fmt" func iMap(num []int, f func(a int) int) []int{ var r []int for _ ...

  7. BOM对象和DOM对象

    一.BOM对象 BOM(Browser Object Model)是指浏览器对象模型,可以对浏览器窗口进行访问和操作.使用 BOM,开发者可以移动窗口.改变状态栏中的文本以及执行其他与页面内容不直接相 ...

  8. MySQL之索引以及正确使用索引

    一.MySQL中常见索引类型 普通索引:仅加速查询 主键索引:加速查询.列值唯一.表中只有一个(不可有null) 唯一索引:加速查询.列值唯一(可以有null) 组合索引:多列值组成一个索引,专门用于 ...

  9. scrapy框架的日志等级和请求传参, 优化效率

    目录 scrapy框架的日志等级和请求传参, 优化效率 Scrapy的日志等级 请求传参 如何提高scripy的爬取效率 scrapy框架的日志等级和请求传参, 优化效率 Scrapy的日志等级 在使 ...

  10. LINUX应用开发(面试)

    LINUX应用开发工程师职位 本试卷从考试酷examcoo网站导出,文件格式为mht,请用WORD/WPS打开,并另存为doc/docx格式后再使用 说明:应用开发可考察的点非常多,关键的还是C语言和 ...