首先,状态转移方程很好想,dp【i】 = min( dp【j】 ) +p【i】
但是这里的L很大,怎么办呢,可以发现,M很小,当L特别大的时候有些石子间的距离会非常大,在这石子间进行状态转移的时候dp里面的值会变得都一样,比方说两个石子间距离是10000与100到最后dp到这个石子的时候,能用的状态都是一样的。。。所以直接将较大的距离直接压缩成100或者1000
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int X[110];
int S, T, M, L;
int p[200000];
int dp[230000];
int main(){
while( scanf( "%d", &L ) != EOF ){
cin >> S >> T >> M;
for( int i = 1; i <= M; i++ ){
cin >> X[i];
}
if( S == T ){
int ans = 0;
for( int i = 1; i <= M; i++ ){
if( X[i] % S == 0 ){
ans++;
}
}
cout << ans << endl;
continue;
}
X[0] = 0;
X[M+1] = L;
sort( X + 1, X + M + 2 );
int len = 0;
memset( p, 0, sizeof( p ) );
for( int i = 1; i <= M + 1; i++ ){
if( X[i] - X[i-1] > 1000 ){
p[len+1000] = 1;
len += 1000;
}else{
p[len+X[i]-X[i-1]] = 1;
len += X[i] - X[i-1];
}
}
L = len;
p[L] = 0;
p[0] = 0;
memset( dp, 0x3f, sizeof( dp ) );
dp[0] = 0;
for( int i = 1; i <= len + T - 1; i++ ){
for( int j = i - T; j <= i - S; j++ ){
if( j >= 0 ){
dp[i] = min( dp[i], dp[j] + p[i] );
}
}
}
int ans = 0x3f3f3f3f;
for( int i = L; i <= len + T - 1; i++ ){
ans = min( ans, dp[i] );
}
cout << ans << endl;
}
return 0;
}