NOIp提高组 2005 过河————dp+路径压缩

感情迁移 提交于 2019-12-02 12:09:44

题解:本题主要考查dp+路径压缩。
简要题意:有一条n(n<=109)n(n<=10^9)米长的桥,桥上有mm个石头。小青蛙从桥头开始,向终点跳。跳跃距离为SSTT,求青蛙最少需要踩到的石子数。
1.dp:本题的难点不在dp的转移方程上,易得出:设f[i]f[i]为在ii上经过的石头数
位置上有石头:f[i]=min(f[i],f[ij]+1);f[i]=min(f[i],f[i-j]+1);
位置上无石头:f[i]=min(f[i],f[ij]);f[i]=min(f[i],f[i-j]);
2.路径压缩:本题nn的规模极大,但mm很小,所以就需要巧妙的路径压缩。我们发现sts*t以后的每个点都可以到达, 所以我们只需将每两个石头超过sts*t的距离缩成sts*t就可以了
代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int stone[233333],v[999999],f[233333],a[233333];
int n,s,t,m,ans=0x3f3f3f,d;
int main()
{
	cin>>n>>s>>t>>m;
	for(int i=1;i<=m;i++)cin>>stone[i];
	sort(stone+1,stone+m+1);
	if(s==t)
	{
		int sum=0;
		for(int i=1;i<=m;i++)
		if(stone[i]%s==0)sum++;
		cout<<sum<<endl;cin>>n;
		return 0;
	}
	for(int i=1;i<=m;i++)
	{
		d=stone[i]-stone[i-1];
		if(d>s*t)d=s*t;
		a[i]=a[i-1]+d;
		v[a[i]]=1;
	}
    if(a[m]+s*t<n)
	n=a[m]+s*t;
	memset(f,0x3f3f3f,sizeof(f));
	f[0]=0;
	for(int i=1;i<=n;i++)
	for(int j=s;j<=t;j++)
	if(i>=j)
	{
		if(v[i]==1)f[i]=min(f[i],f[i-j]+1);
		else f[i]=min(f[i],f[i-j]);
	}
	for(int i=1;i<=n;i++)
	ans=min(ans,f[n]);
	cout<<ans<<endl;
	return 0;
} 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!