洛谷 P1052 过河(DP+离散化)

题目链接:https://www.luogu.com.cn/problem/P1052

方程比较好像:

设f[i]表示跳到第i个点的最少石子数。

那么f[i]=min(f[i],f[i-j]+vis[i]),vis[i]代表第i个点有没有石子,s<=j<=t。

但是这样的话f的下标大小应为1e9,显然不可能。所以要进行离散化。

如果两点之间的距离小于t,那么可以让距离%t,然后再加t(因为两个点可能本来距离为t的倍数,一取模则就当成了同一个点),再用上一个点的左标加上这个距离,即为当前点的坐标。

这样就可以将数组的下标的范围压小,转移相同。

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=1005;
 7 int l,s,t,m,cnt;
 8 int ans=0x7f7f7f;
 9 int a[N],d[N],vis[N],f[N];
10 int main(){
11     memset(f,0x7f7f7f,sizeof(f));
12     scanf("%d%d%d%d",&l,&s,&t,&m);
13     for(int i=1;i<=m;i++) scanf("%d",&a[i]);
14     a[m+1]=l;
15     sort(a,a+m+2);
16     for(int i=1;i<=m+1;i++) d[i]=a[i]-a[i-1];
17     for(int i=1;i<=m+1;i++){
18         if(d[i]>t) cnt+=d[i]%t+t;
19         else cnt+=d[i];
20         vis[cnt]=1;
21     }
22     f[0]=0;
23     for(int i=1;i<=cnt+t-1;i++){
24         for(int j=s;j<=t;j++){
25             if(i-j>=0) f[i]=min(f[i],f[i-j]+vis[i]);
26         }
27     }
28     for(int i=cnt;i<=cnt+t-1;i++) ans=min(ans,f[i]);
29     printf("%d",ans);
30     return 0;
31 }
AC代码
原文地址:https://www.cnblogs.com/New-ljx/p/13899634.html