过河

https://www.luogu.com.cn/problem/P1052

设f[i]表示到达i位置最少踩到石子个数

f[i]从f[i-t]到f[i-s]转移

但是l太大要压缩路径

1.根据小凯的疑惑中的结论

方程px+(p+1)y=z,当z>=p(p+1)-p-(p+1)时一定有解

在本题中步数最多为10,即p+1最多为10

所以当两点距离大于等于72时一定能从前一个点到后一个点

我们可以把这样的两个点的距离直接变成72

即把所有石子的距离模73

注意原题中s可以等于t,这时不存在p和p+1两种决策

所以需要特判一下,s=t&&石子坐标%s=0答案加一

2.https://www.luogu.com.cn/blog/yzp2846799957/solution-p1052

在s和t的最小公倍数之后的点都可以走到

可以用s*t缩点

或者1~10的最小公倍数2520缩点

3.随便用个大一点而且不会t的数缩点,,用了1000没有特判,,不知道为什么ac了,,,

#include<bits/stdc++.h>
using namespace std;
int a[1000000],dp[1000000],tt[1000000];
bool cmp(int x,int y)
{
	return x<y;
}
int main()
{
	int l,s,t,x,sum=0,m,ans=0x3f3f3f3f;
	memset(dp,0x3f,sizeof(dp));
	memset(a,0,sizeof(a));
	cin>>l>>s>>t>>m;
	for(int i=1;i<=m;i++) 
	{
		cin>>a[i];
	}
	if(s!=t)
	{
		sort(a+1,a+1+m,cmp);
		for(int i=0;i<m;i++)
		{
			if(a[i+1]-a[i]>1000) sum=(a[i+1]-a[i])/1000*1000;
			a[i+1]-=sum;
			tt[a[i+1]]=1;
		}
		if(l-a[m]>1000) l-=(l-a[m])/1000*1000;
		dp[0]=0;
		for(int i=1;i<=l+t;i++)
		{
			for(int j=max(0,i-t);j<=i-s;j++) 
			if(tt[i]) dp[i]=min(dp[i],dp[j]+1);
			else dp[i]=min(dp[i],dp[j]);
			//QAQif(a[i]) dp[i]++;
		}
		for(int i=l;i<=l+t;i++) 
		{
			ans=min(ans,dp[i]);
		}
		cout<<ans;	
	}
	else 
	{
		ans=0;
		for(int i=1;i<=m;i++) if(a[i]%s==0) ans++;
		cout<<ans;
	}
	return 0;
}

hack

https://www.luogu.com.cn/discuss/show/29232

缩点的过程中把一个区间变成了一个点,如果x,y都是石子,本来可以从x-1转移到y-1在缩点后必须要踩石子,也许可以特判一下?不懂QAQ

原文地址:https://www.cnblogs.com/qwq-/p/13563284.html