• 洛谷1052——过河(DP+状态压缩)


    题目描述

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

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

    输入输出格式

    输入格式:

    第一行有11个正整数L(1L109)L(1 le L le 10^9),表示独木桥的长度。

    第二行有33个正整数S,T,MS,T,M,分别表示青蛙一次跳跃的最小距离,最大距离及桥上石子的个数,其中1ST101 le S le T le 10,1M1001 le M le 100

    第三行有MM个不同的正整数分别表示这MM个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

    输出格式:

    一个整数,表示青蛙过河最少需要踩到的石子数。

    输入输出样例

    输入样例#1:

    10
    2 3 5
    2 3 5 6 7
    

    输出样例#1:

    2
    

    说明

    对于30%的数据,L10000L le 10000

    对于全部的数据,L109L le 10^9

    2005提高组第二题

    思路

    如果不考虑数据范围的话,可以很快得出递推关系式:dp[i]=min(dp[i+k]+a[i])  (SkT)dp[i]=min(dp[i+k]+a[i]) (Sleq k leq T)a[i]a[i]ii点的石头数dp[i]dp[i]表示到达ii点踩到的最少石头数)

    然鹅看了数据范围后,时间和空间都是过不去的。所以需要选择别的方法:

    • S=TS=T的时候,可以很容易得到:所有在SS倍数位置上的点,都会走到,所以对该种情况进行特判

    • 我们可以发现石子在桥上放置的是非常稀疏的,而且当点的位置超过一定范围,点都是可以跳到的。所以可以将石子所在的位置压缩到这个范围里去。将压缩后位置储存起来作为新的石头的位置,按照这个位置进行dp即可

    假设每次走pp或者p+1p+1步.我们知道gcd(p,p+1)=1gcd(p,p+1)=1.
    由扩展欧几里得可知,对于二元一次方程组:
    px+(p+1)y=gcd(p,p+1)px+(p+1)y=gcd(p,p+1)是有整数解的,即可得:px+(p+1)y=spx+(p+1)y=s是一定有整数解的。
    px+(p+1)y=spx+(p+1)y=s的解为:x=x0+(p+1)t,y=y0ptx=x_0+(p+1)t,y=y_0−pt。令0xp0leq xleq p(通过增减ttp+1p+1来实现),s>p×(p+1)1s>p imes (p+1)−1
    则有:y=spxp+1sp2p+1>p(p+1)1pxp+10y=dfrac {s-px}{p+1}geq dfrac {s-p^{2}}{p+1} >dfrac {pleft( p+1 ight) -1-px}{p+1}geq 0
    即表示,当sp×(p+1)sleq p imes (p+1)时,px+(p+1)y=spx+(p+1)y=s有两个非负整数解,每次走pp步或者p+1p+1步,p×(p+1)p imes (p+1)之后的地方均能够到达。
    如果两个石子之间的距离大于p×(p+1)p imes (p+1),那么就可以直接将他们之间的距离更改为p×(p+1)p imes (p+1)
    综上,得到压缩路径的方法:若两个石子之间的距离大于t×(t1)t imes(t−1),则将他们的距离更改为t×(t1)t imes (t−1)

    t10为tleq10,因此我们可以直接将大于10×910 imes9的距离直接化为9090.

    关于路径压缩常数的选择,证明过程详见:https://blog.csdn.net/qq_34940287/article/details/77494073

    AC代码

    /*************************************************************************
    
    	 > Author: WZY
    	 > School: HPU
    	 > Created Time:   2019-02-03 15:55:49
    	 
    ************************************************************************/
    #include <bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define ms(a,b) memset(a,b,sizeof(a))
    #define INF 0x7f7f7f7f
    const int maxn=1e6+10;
    const int mod=1e9+7;
    using namespace std;
    int a[maxn];
    int dp[maxn];
    int vis[maxn];
    int main(int argc, char const *argv[])
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	int L;
    	int ans=0;
    	int s,t,m;
    	cin>>L;
    	cin>>s>>t>>m;
    	for(int i=1;i<=m;i++)
    		cin>>a[i];
    	if(s==t)
    	{
    		for(int i=1;i<=m;i++)
    		{
    			if(a[i]%s==0)
    				ans++;
    		}
    		cout<<ans<<endl;
    		return 0;
    	}
    	sort(a+1,a+1+m);
    	int _=90;
    	int res=a[1]%_;
    	vis[res]=1;
    	// 缩点
    	for(int i=2;i<=m;i++)
    	{
    		res+=(a[i]-a[i-1])%_;
    		vis[res]=1;
    	}
    	for(int i=res;i>=0;i--)
    	{
    		dp[i]=INF;
    		for(int j=s;j<=t;j++)
    			dp[i]=min(dp[i],dp[i+j]+vis[i]);
    	}
    	cout<<dp[0]<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    软件测试进程&测试类型
    课堂笔记:软件测试知识点汇总小结
    闰年测试程序
    关于 int.parse("abcd") 出错的问题分析及解决方案
    软件测试——字符串检测2.0
    边界值分析法实例分析
    测试管理
    软件评审
    单元测试与集成测试
    白盒测试
  • 原文地址:https://www.cnblogs.com/Friends-A/p/11054978.html
Copyright © 2020-2023  润新知