(Luogu) P1052 过河 (状压dp)

 传送门

解题思路:这题的状态转移方程还是很好想的,dp[i]代表跳到第i点踩到的最少石头,dp[i]=dp[i-j]+stone[i],j位距离,即跳j个距离到i点,stone[i]表示这里是否有石子。但是这里l非常大,只是循环也会超时,所以需要状态压缩。这里压缩的方法有90缩,72缩(戳我)还有2520缩,这里我写的是2520缩,这个很好理解,2520是1~10的最小公倍数,就是从i点出发,每个点都可以到达距离+2520处,之后又会出现重复的情况,所以只要对2520取余就行了,最大也就是2520*100。


#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=1e6+5;
const int mod=2520;
int dp[maxn];
int stone[maxn],a[maxn];
int l,s,t,m;
int main(){
	std::ios::sync_with_stdio(0);
	cin>>l>>s>>t>>m;
	for(int i=1;i<=m;++i){
		cin>>a[i];
	}
	sort(a+1,a+m+1);
	int k=0;
	for(int i=1;i<=m;++i){
		if(a[i]-a[i-1]>mod){ //距离大了
			k+=(a[i]-a[i-1])-(a[i]-a[i-1])%mod;
		}
		stone[a[i]-k]=1;
	}
	memset(dp,0x3f,sizeof(dp));
	dp[0]=0;
	for(int i=1;i<=mod*m;++i){
		for(int j=t;j>=s;--j){
			if(i-j>=0){
				dp[i]=min(dp[i-j]+stone[i],dp[i]);
			}
		}
	}
	cout<<dp[mod*m]<<endl;
	return 0;
}




猜你喜欢

转载自blog.csdn.net/TDD_Master/article/details/86509135