P1052 升级的状压DP

链接: https://www.luogu.org/problemnew/show/P1052

AC代码:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;

int stone[109],f[350000],dis[109];
ll dp[350000];

int main() {
	int len,maxn,minn,num;
	cin>>len>>minn>>maxn>>num;
	for(int i=1; i<=num; i++) {
		cin>>stone[i];
	}
	sort(stone+1,stone+num+1);//输入工作

	for(int i=1; i<=num; i++) {//2520是 1-10 的最小公倍数,所以两点相隔2520以上时,可以砍去一些距离
		dis[i]=(stone[i]-stone[i-1])%2520;
	}
	for(int i=1; i<=num; i++) {
		stone[i]=stone[i-1]+dis[i];//压缩路径后的石头相对位置
		f[stone[i]]=1;//压缩路径之后的石头绝对位置
	}
	len=stone[num];//压缩路径之后的路径长度
	
	fill(dp,dp+len+maxn+1,0x3f3f3f3f);
	dp[0]=0;//起点没有石头,赋值为0 
	
	for(int i=1;i<=len+maxn;i++){//因为可能跳过终点,所以最后到达的是一个范围,而不是一个具体的点 
		for(int j=minn;j<=maxn;j++){
			if(i>=j){
				dp[i]=min(dp[i],dp[i-j]);
				if(f[i]){
					dp[i]+=1;//枚举每个可能走的步数,如果有石头就 +1
				} 
			}
			
		}
	}
	
	ll ans=0;
	for(int i=len;i<len+maxn;i++){
		ans=min(dp[i],dp[i+1]);//最后到达的是一个范围,这个范围内都算到达终点,所以选择一个踩到石头数量最少的 
	}
	cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/StarrYooSkY/article/details/86544907