zoukankan      html  css  js  c++  java
  • P1052 过河[DP]

    题目描述

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

    题目给出独木桥的长度LL,青蛙跳跃的距离范围S,TS,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

    解析

    正常来讲,这是一道再简单不过的dp,状态定义就是到达每个点最少踩到的石子数,转移就是从前(ssim t)步的状态转移过来。

    但是,这题数据范围很大,于是运用压缩路径技巧。

    显然,如果我们取(1sim10)的最小公倍数,若两点之间距离为这个最小公倍数,那么无论(s,t)为何,都可以从上一个点跳到这一个点。因此,我们每遇到两个距离大于该最小公倍数的点,就将这个距离对该最小公倍数取模。

    参考代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define N 350000
    #define E 1e-12
    #define lcm 2520
    using namespace std;
    int dp[N],a[N],d[N],l,s,t,m;
    bool v[N];
    int main()
    {
    	scanf("%d%d%d%d",&l,&s,&t,&m);
    	for(int i=1;i<=m;++i) scanf("%d",&a[i]);
    	sort(a+1,a+m+1);
    	for(int i=1;i<=m;++i) d[i]=(a[i]-a[i-1])%lcm;
    	for(int i=1;i<=m;++i){
    		a[i]=a[i-1]+d[i];
    		v[a[i]]=1;
    	}
    	l=a[m];
    	fill(dp+1,dp+N,m);
    	for(int i=0;i<=l+t;++i)
    		for(int j=s;j<=t;++j){
    			if(i-j>=0) dp[i]=min(dp[i],dp[i-j]);
    			dp[i]+=v[i];
    		}
    	int ans=INF;
    	for(int i=l;i<=l+t;++i)
    		ans=min(ans,dp[i]);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    WPF-ListView单元格设置文字换行
    WPF-GridView设置列宽按比例分配
    C#控制台输入密码星号显示
    安装pycharm
    超强的链接2
    redis
    day 46 htmljianjie
    day45 html超文本标记语言
    43 非阻塞 io多路复用
    42 队列 线程池 协程 geven模块 协程完成的socket
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11388109.html
Copyright © 2011-2022 走看看