code1105 过河

dp方程很简单:

f[i] = min{ f[i-j] } + stone[i]

但是数据10^9太大了,超时超空间,这样只能过30%

来自:http://blog.csdn.net/w19960702123/article/details/40478187

当我们看到10^9与100块石头,和s,t均小于等于10时,我们会想到有的石头间距可能大于t,即要跳好几步才会到达下一块石头的左右处。而我们会发现这些步数是无关紧要的,我们只需要把他们缩小,即在不影响最终结果的基础上mod一下t就行了。

但是为什么要mod t呢?首先,我们可以知道,青蛙最多跳t,由于两石块间的间距远大于t,且这之间没有石头,所以青蛙会以最大的t去走,至少是在第i块石头向后t个距离,到第i+1块向前t个距离处,它会一直跳的(其实不跳t也可以,但是我们想最优,所以青蛙在中间如何跳是无所谓的,那么我们就可以把它极限化,即取t)

解释完mod t,先一步就是推导如何计算了。

既然我们要缩短距离L(L=b[i]-b[i-1])那么我们就需考虑,是不是L的每一个点都能缩。我们利用极限的思想,青蛙跃过一个石头,最多也就到b[i-1]+t处(同理,最少会到b[i] - t ),即 b[i-1]+t 到 b[i] - t 间的距离要缩减。

综上,我们就可以得到一个公式a[i]=a[ i-1]+X , X=(b[i]-t-b[i-1]-t)%t (即缩点后的长度),但是我们怕X会小于t,这样会导致青蛙直接跳过这段距离,所以我们要再加t,即a[i]=a[ i-1]+(b[i]-b[i-1]-2*t)%t +t。

注意:

1.我们只有在L>t 时我们需要缩点

2.不要忘记排序

3.讨论s==t的情况

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int f[100000],a[105],b[105],stone[100000];
int L,s,t,m,ans;
int main()
{
    cin>>L>>s>>t>>m;
    for(int i=1;i<=m;i++)cin>>a[i];
    a[0]=0;
    sort(a+1,a+m+1);
    //特判
    if(s==t){
        for(int i=1;i<=m;i++)if(a[i]%t==0)ans++;
        cout<<ans;
        return 0;
    }
    //压缩
    a[m+1]=L;
    for(int i=1;i<=m+1;i++){
        if(a[i]-a[i-1]>t)
            b[i]=b[i-1]+(a[i]-a[i-1]-2*t)%t+t;
        else b[i]=b[i-1]+(a[i]-a[i-1]);
//        cout<<b[i]<<endl;
    }
    L=b[m+1];

    memset(stone,0,sizeof(stone));
    for(int i=1;i<=m;i++)stone[b[i]]=1;
    f[0]=0;
    for(int i=1;i<=L+t-1;i++)f[i]=0x3f3f3f3f;
    //dp
    for(int i=1;i<L+t;i++)
         for(int k=s;k<=t;k++)
             if(i-k>=0)f[i]=min(f[i-k]+stone[i],f[i]);
    //ans
    ans=0x3f3f3f3f;
    for(int i=L;i<L+t;i++)ans=min(ans,f[i]);
    cout<<ans;

    return 0;
}
时间: 2024-10-10 11:23:00

code1105 过河的相关文章

洛谷 【P1052】过河

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

贪心—— P1809 过河问题_NOI导刊2011提高(01)

洛谷——P1809 过河问题_NOI导刊2011提高(01) 题目描述 有一个大晴天,Oliver与同学们一共N人出游,他们走到一条河的东岸边,想要过河到西岸.而东岸边有一条小船. 船太小了,一次只能乘坐两人.每个人都有一个渡河时间T,船划到对岸的时间等于船上渡河时间较长的人所用时间. 现在已知N个人的渡河时间T,Oliver想要你告诉他,他们最少要花费多少时间,才能使所有人都过河. 注意,只有船在东岸(西岸)的人才能坐上船划到对岸. 输入输出格式 输入格式: 输入文件第一行为人数N,以下有N行

马拦过河卒心得体会

题目棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为"马拦过河卒". 棋盘用坐标表示,A点(0, 0).B点(n, m)(n, m为不超过15的整数),同样马的位置坐标是需要给出的.现在要求你计算出卒从A点能够到达B点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步. 输入一行四个数据,分别表示B点坐标和马的坐标.(保证所有的数据有解) 输出一个数据

NOIP2005 过河

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

hdu 4842(NOIP 2005 过河)之 动态规划(距离压缩)

/* hdu 4842(NOIP 2005 过河)之 动态规划(距离压缩) dp[i] := 到桥上的i位置,最少需要踩到的石子数. dp[i] = min(dp[i], dp[i-j] + isStone[i])    条件: (1) S<=j<=T (2) dp[i-j]是青蛙可以到达的点 独木桥长度L,最大为10^9,直接用转移方程,TLE:由于桥上的石子个数100,所以当石子分布在独木桥上时,是很稀疏的. (1)S!=T 考虑,对于此题关键在于求踩到的石子数,而非跳的次数,对于两个相邻

商人过河问题(DFS)

问题描述:3个商人带着3个仆人过河,过河的工具只有一艘小船,只能同时载两个人过河,包括划船的人.在河的任何一边,只要仆人的数量超过商人的数量,仆人就会联合起来将商人杀死并抢夺其财物,问商人应如何设计过河顺序才能让所有人都安全地过到河的另一边. 详细过程参见<数学模型>第四版(姜启源) #include <cstdio> #define maxn 101 int num;//number of bus or fol int graph[maxn*maxn][maxn*maxn]; i

【水】noip2002普及 过河卒

这题似乎是当年的马拦过河卒,好久的回忆啊... 过河卒 来源 NOIP2002普及组 题目描述 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例 如上图 C 点上的马可以控制 9 个点(图中的P1,P2 … P8 和 C).卒不能通过对方马的控制点. 棋盘用坐标表示,A 点(0,0).B 点(n,m)(n,m 为不超过 25 的整数,并由键盘输入),同样马的

Vijos P1002 过河 (NOIP提高组2005)

链接:https://www.vijos.org/p/1002 解析: 若 p*x+(p+1)*y=Q(采用跳跃距离p和p+1时可以跳至任何位置Q),则在Q ≥ P*(P-1)时是一定有解的. 由于题目给出的一个区间是1≤S≤T≤10,于是当相邻的两个石子之间的距离不小于8*9=72时,则后面的距离都可以到达,我们就可以认为它们之间的距离就是72.如此一来,我们就将原题L的范围缩小为了100*72=7200,动态规划算法完全可以承受了. 但是当S=T时,上述等式是无法使用的,在这种情况下,只需要

P1244 青蛙过河

P1244 青蛙过河 题目描述 有一条河,左边一个石墩(A区)上有编号为1,2,3,4,-,n的n只青蛙,河中有k个荷叶(C区),还有h个石墩(D区),右边有一个石墩(B区),如下图所示.n只青蛙要过河(从左岸石墩A到右岸石墩B),规则为: (1)石墩上可以承受任意多只青蛙,荷叶只能承受一只青蛙(不论大小): (2)青蛙可以:A→B(表示可以从A跳到B,下同),A→C,A→D,C→B,D→B,D→C,C→D: (3)当一个石墩上有多只青蛙时,则上面的青蛙只能跳到比它大1号的青蛙上面. 你的任务是