[NOIP2005]长者过河 题解

来源:互联网 发布:如何写出二次型的矩阵 编辑:程序博客网 时间:2024/04/29 05:51

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

【输入文件】输入文件river.in的第一行有一个正整数L(1 <= L <= 109),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1 <= S <= T <= 10,1 <= M <= 100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。【输出文件】输出文件river.out只包括一个整数,表示青蛙过河最少需要踩到的石子数。【样例输入】102 3 52 3 5 6 7 【样例输出】2 【数据规模】对于30%的数据,L <= 10000;对于全部的数据,L <= 109。

由于数据太大,一般要缩点,如大于t*(t-1),就缩为t*(t-1),注意最后要在dis[m]–dis[m+t]中找最大值!!!!!,不一定会是刚好跳在dia[m]处。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int l,s,t,m,a[105],b[105],sum = 0,f[10005],stone[10000];int dis[105][2];int find(int x) {    for(int i = 1; i <= m; i++ )        if(a[i] == x) return i;    return 0;}int main() {    freopen("river.in","r",stdin);    freopen("river.out","w",stdout);    scanf("%d%d%d%d", &l, &s, &t, &m);    for(int i = 1; i <= m; i++ ) scanf("%d", &a[i]);    if(t == s){        for(int i = 1; i <= m; i++ ) if(a[i] % t == 0) sum++;        printf("%d",sum);        return 0;    }    sort(a+1,a+m+1);    int i,j;    for(int k = t*(t-1),j = 0,i = 1; i <= m; i++) {//缩点        a[i]-=j;int x=a[i]-a[i-1];        if(x>k)j+=x-k,a[i]=a[i-1]+k;    }    memset(f,127,sizeof(f));    for(i = 1; i <= m; i++ )        stone[a[i]] = 1;f[0] = 0;    for(i = 0; i <= a[m]; i++ )        for(j = s; j <= t; j++ )        f[i+j] = min(f[i+j],f[i] + stone[i+j]);    for(sum = f[a[m]],i = s; i < t; i++ ) sum = min(sum,f[a[m]+i]);    printf("%d",sum);    return 0;}
0 0
原创粉丝点击