Vijos 1002 crossing the river and vijos1002 crossing the river
This is my first question on Vijos. I did this question when I just finished learning DP. At that time, I was very young and frivolous. I didn't look at the scope of the data. I directly went to the brute force DP, and the result was TLE .... I never touched it again later. I know that I think it is almost time for the provincial competition. It is necessary to do the questions I did not have, so I had this blog.
After learning the simplest motion rules at that time, I learned another algorithm called the pressure DP. The pressure is the State compression, and all useless states are excluded. BZOJ has a question about pressing DP (not infringing king !! The question of crossing the river is a pressure of DP. Based on my current habits, let's look at the data range first and then determine the algorithm. (1 <= L <= 10 ^ 9) log-level algorithms should be used based on experience for such a large number, but obviously no log-level algorithms can be used for the questions. It should be DP. Since DP has such a large data range, it should be a type of pressure DP. In this way, the algorithm is determined. So how to compress it? A Theorem is used here.
Px + (P + 1) y = Q
X, y is unknown, P is the Jump Distance, P + 1 is also the jump distance, for any Q, Q> = P * (P-1), x, y must have a positive integer solution, in other words, when the distance between the two stones is greater than or equal to T * (T-1), there is a considerable distance between each point can jump to, because there is no stone, so there is no contribution to the answer. You can use the modulo (% 90), so it is easy to do... So we successfully compress the status.
Note: stones are not sorted in order.
Code:
#include<iostream>#include<cstdio>#include<algorithm>#define inf 1<<30using namespace std;int l,s,t,m,f[900000],pos[200],a[900000];void slove(){ int ans=0; for(int i=1;i<=m;i++) if(pos[i]%s==0) ans++; printf("%d",ans);}int main(){ scanf("%d%d%d%d",&l,&s,&t,&m); for(int i=1;i<=m;i++) scanf("%d",&pos[i]); sort(pos+1,pos+m+1); if(s==t){ slove(); return 0; } for(int i=1;i<=m;i++){ int temp=pos[i]-pos[i-1]; pos[i]=pos[i-1]+temp%90; } l=pos[m]+(l-pos[m])%90; for(int i=1;i<=m;i++) a[pos[i]]=1; for(int i=1;i<=l;i++) f[i]=inf; f[0]=0; for(int i=1;i<=l;i++) for(int j=s;j<=t;j++) if(i-j>=0) f[i]=min(f[i-j]+a[i],f[i]); printf("%d",f[l]);}