过河 【状态压缩DP】+【完整的数论推导过程】

2023-11-08

题目链接

  题意:很多人以为青蛙是要跳到石头上,一个个往后跳,问最少需要的石头数量,其实不然(题目给的样例的确也是有些坑了),青蛙每次都有跳的距离范围,题目求的是最少会跳到的石头,青蛙可以在水中起跳,它要尽可能的避开石头,也就是问抵达终点时最少需要必经的石头数。

思路

  路很长,石头很少,很多次起跳绝对是在水里折腾,那么我们不如去优化这段在水里折腾的路径,反正在水里折腾的那部分时间不用计算到和里去。

  • 如何路径压缩?

  在写上标准解之前,我先举这样的例子:假如S=4;T=5。那么到达哪一步的时候,青蛙能到达它之后的每一步?

  从0开始:0 4 5 8 9 10 12 13 14 15 16 17 18......发现一件事,从12开始,后面的每一步都可以由0开始经过一系列步伐之后得到,那么假如0~12这段间没有石头,我们就可以把石头距0所在的位置去%12 ,就能优化这段的路径。

  这是不是一个规律呢?或者存粹就是个偶然,不,我们可以距离其他数据,发现我们可以去“%((S-1)*(T-1))”去得到路径优化。那么,为什么会存在这样的一个规律,我们需要去找到其缘由

  知道S与T,我们欲求得当它走到哪一步的时候,步步可走?(求极端值的想法,因为S与T差别越大,就说明其中点越多,越容易找到所求状态,所以我取S与T相邻情况)

第一次处理:S, T

第二次处理:2S, S+T, 2T

第三次处理:3S,2S+T,S+2T,3T

第四次处理:4S, 3S+T,2S+2T,S+3T,4T

......

第N次处理:NS,(N-1)S+T,......,S+(N-1)T,NT

我们需要处理到:N*T+1==(N+1)*S这样的一步,就说明链接上了,转移一下方程:(N+1)*S-N*T=1,将其中S与T看作是函数的两个变量,就得到了拓展欧几里得的这样的一个方程。又有gcd(N, N+1)恒等于1,故恒有两个大于零的解,即有解。那么,我们把S和T分别取到极限相邻值(9,10),就能发现,它们在第8次操作之后:72,73,74,75,......就是恒为所求状态,而所求模也就是(S-1)*(T-1)。但当S==1时,会使得S-1==0,故极限最长区间,我们令它为90(当然,80之类的也是可以,别取太小,毕竟还有极限值)。

  • 状态转移方程:

  处理出要压缩的距离之后,我们知道每次需要压缩的距离,对于已经排序好的两两点,我们从前往后查询两两点之间的距离,如果它们的距离大于需要mod(90)的值,就将它们mod掉。

  处理完距离之后,就是状态转移方程,对应dp[i]=min(dp[i], dp[i-j]+live[i]),其中j的范围是[S, T],live[i]指的是这个点是否有石头。

 

完整代码:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef long long ll;
const int maxN=9999;        //状压,拓欧可见规律在于T*(T-1)
int L, S, T, M;
int mp[110], dp[maxN<<2];      //mp[]记录原先距离原点的距离,dp[]记录到达这个点最小次数
bool live[maxN<<2];        //状压后判断这个点是否存在点?
bool cmp(int e1, int e2)
{
    return e1<e2;
}
int main()
{
    while(scanf("%d",&L)!=EOF)
    {
        mp[0]=0;        fill(dp, dp+maxN-1, maxN);      memset(live, false, sizeof(live));
        scanf("%d%d%d",&S,&T,&M);       int mod=80;
        for(int i=1; i<=M; i++) scanf("%d",&mp[i]);
        sort(mp+1, mp+1+M, cmp);  mp[M+1]=L;
        if(S==T)        //此时每次只能走固定点,需要独立考虑
        {
            int ans=0;
            for(int i=1; i<=M; i++) if(!(mp[i]%S)) ans++;       //能整除就说明这个点一定得走
            printf("%d\n", ans);
            continue;
        }
        for(int i=1; i<=M+1; i++)     //状压,包括要更改至end节点(没石头)
        {
            if(mp[i]-mp[i-1]>mod) mp[i]=mp[i-1]+(mp[i]-mp[i-1])%mod;
            live[mp[i]]=true;
        }
        dp[0]=0;
        for(int i=S; i<=T; i++) dp[i]=live[i];      //定义每个初始dp节点
        for(int i=2*S; i<=mp[M+1]; i++)
        {
            for(int j=S; j<=T && j<=i; j++)     //能抵达i点的点的最小石头利用次数
            {
                dp[i]=min(dp[i], dp[i-j]);
            }
            dp[i]+=live[i];
        }
        printf("%d\n", dp[mp[M+1]]-1);
    }
    return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

过河 【状态压缩DP】+【完整的数论推导过程】 的相关文章

随机推荐

  • CSS中关于z-index的堆叠顺序

    1 同级的z index div class container div class div1 h1 Division Element 1 z index 10 h1 div div class div2 h1 Division Eleme
  • Vs2019简单快速的打包可安装项目(图文教程)

    声明本项目在已安装vs2019和加载了installer Projects的情况下才能操作 右键解决方案 gt 添加 gt 新建项目 新建一个Setup Project 进入这个页面 右键Application Foluder gt Add
  • CVPR 2023

    作者 张倩 小舟 来源 机器之心 在文生图领域 扩散模型似乎已经一统天下 让曾经也风头无两的 GAN 显得有些过时 但两相比较 GAN 依然存在不可磨灭的优势 这使得一些研究者在这一方向上持续努力 并取得了非常实用的成果 相关论文已被 CV
  • 遍历Github仓库并提取所有图片

    遍历Github仓库并提取所有图片 项目介绍 一个简易的Github图床客户端 项目仓库 GithubImageHost 利用 QElapsedTimer QCoreApplication processEvents 可是实现UI同步 QE
  • html静态页面中引入scss的样式调整

    问题 静态页面样式和vue动态页面的样式不统一 截图了一个角落 需求 静态页面的样式要和动态页面的一样 解决步骤 F12 查看样式文件引用的区别 找到vue动态页面中的样式区别是在vue项目中用了自带的scss文件 将文件引入到静态页面的文
  • SSH通道的Kettle链接MySQL方法

    参考文献 http www ukettle org thread 452 1 1 html 对于采用SSH通道的MySQL服务器 Kettle无法直接连接 需要使用到 使用 SSH 工具 PUTTY
  • yolov5的TensorRT部署--warpaffine_cuda核函数

    从0到1实现基于tensorrt的yolo部署教程 http t csdn cn HUn4T 请点击该链接 即可看到全文 本文对于上面的案例 将预处理使用cuda核函数进行加速 一 cuda核函数的基本概念 1 1 CUDA C基础 核函数
  • Redis入门(一)

    1 简介 Redis 是完全开源的 遵守 BSD 协议 是一个高性能的 key value 数据库 Redis 与其他 key value 缓存产品有以下三个特点 Redis支持数据的持久化 可以将内存中的数据保存在磁盘中 重启的时候可以再
  • 计算机组成原理实验二 存储系统预习报告

    实验一 静态RAM 一 实验目的 掌握静态随机存储器 RAM 工作特性及数据的读写方法 基于信号时序图 了解读写静态随机存储器的原理 二 实验预习 1 阅读实验指导书 然后回答问题 实验所用的静态存储器由一片 6116 2K 8bit 构成
  • 离散信号的Matlab表示

    对任意离散序列x k 需用2个向量来表示 一个表示k的取值范围 另一个表示序列的值 例如序列x k 2 1 1 1 3 0 2 可用Matlab表示为 k 2 4 x 2 1 1 1 3 0 2 若序列从0开始 则只用一个向量x就可表示序列
  • 前端开发: 微信小程序 (文字,链接)生成二维码

    首先最主要的还是通过weapp qrcode js 靠这个轮子就可以了 GitHub yingye weapp qrcode weapp qrcode js 在 微信小程序 中 快速生成二维码https github com yingye
  • 人工智能和机器学习

    机器学习 1 什么是机器学习 在进行特定的编程的情况下 给与计算机学习能力的领域 机器学习是从数据中自动分析获得模型 并利用模型对未知数据进行预测 2 机器学习与人工智能 2 1人工智能发展的三个阶段 1980年代是正式形成时期 1990
  • Java接口详解

    http hi baidu com cxgfhfiupuanour item 370967f74ecbe9cca835a2b4 对初学者来说 接口不是很好理解 现将某高手的一篇文章贴出来 共大家分享 我们来看一个类 class A priv
  • 华为UOS欧拉版 K3S+Rancher 安装完全版

    文章目录 K3S服务 happy path安装过程 1 准备工作 1 1 修改网卡名称为eth0 1 2 切换yum源 1 3 关闭防火墙以及selinux 1 4 修改主机名 并修改hosts 1 5 在UOS 基于华为欧拉 上安装doc
  • vue动画之轮播图

  • Vue自定义组件——封装一个简单的可拖拽的弹出框 可拖拽的Dialog

    首先明确需要传入组件的属性 Props dialogVisible Number 非0打开 allowDrag Boolean 是否可以拖拽 noFoot Boolean 是否显示按钮行 submit Function 点击提交按钮的回调
  • Tomcat 环境变量

    到tomcat官方站点 http www apache org dist jakarta tomcat 4 下载tomcat jakarta tomcat 4 1 30 exe 下载之后安装 比如安装在D Tomcat下 安装完之后 设置环
  • AsyncResult 类的使用

    AsyncResult 类封装异步委托上的异步操作的结果 与异步委托一起使用 从该委托的 BeginInvoke 方法返回的 IAsyncResult 可以强制转换为 AsyncResult AsyncResult 具有 AsyncDele
  • 24、【C++】C++11新特性:Lamda表达式/可变参数模板

    一 Lamda表达式 Lamda表达式是C 11中引入的一项新技术 利用Lamda表达式可以编写内嵌的匿名函数 用以替换独立函数或者函数对象 并且使得代码更可读 是一种匿名函数 即没有函数名的函数 Lamda函数的语法定义如下 captur
  • 过河 【状态压缩DP】+【完整的数论推导过程】

    题目链接 题意 很多人以为青蛙是要跳到石头上 一个个往后跳 问最少需要的石头数量 其实不然 题目给的样例的确也是有些坑了 青蛙每次都有跳的距离范围 题目求的是最少会跳到的石头 青蛙可以在水中起跳 它要尽可能的避开石头 也就是问抵达终点时最少