【NOIP】提高组2005 过河

【算法】状态压缩型DP

【题解】

Q=tx+(t-1)y

对于Q≥t(t-1),x,y一定有解。

所以当两石子间距离long>t(t-1)时,令long=t(t-1),重新构造数组即可。

【注意】

1.输入的石子位置无序,要排序。

2.当s=t时特判。

3.最终解要在n~n+t中找最小值(不过数据太水=v=)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=30000,maxm=110;
int a[maxm],b[maxn],f[maxn],l,s,t,n;
int main()
{
    scanf("%d%d%d%d",&l,&s,&t,&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    int ans=0;
    if(s==t)
     {
         for(int i=1;i<=n;i++)if(a[i]%s==0)ans++;
         printf("%d",ans);
         return 0;
     }
    sort(a,a+n+1);     
    int ago=0,mark=0,p=t*(t-1)+1;
    for(int i=1;i<=n;i++)
     {
         if(a[i]-ago>=p)
          b[(mark+=p)]=1;
         else b[(mark=mark+a[i]-ago)]=1;
        ago=a[i];
     }
    if(l-ago>p)
     mark+=p;
    else mark=mark+l-ago;
    memset(f,0x3f,sizeof(f));
    f[0]=0;
    for(int i=s;i<=mark;i++)
     for(int j=s;j<=t;j++)
      {
          f[i]=min(f[i],f[i-j]+b[i]);
      }
/*    for(int i=0;i<=mark;i++)printf("%d ",i);printf("\n");
    for(int i=0;i<=mark;i++)printf("%d ",b[i]);printf("\n");
    for(int i=0;i<=mark;i++)if(f[i]>1000)printf("x ");else printf("%d ",f[i]);*/
    printf("%d",f[mark]);
    return 0;
}
View Code

 

posted @ 2016-09-12 12:55  ONION_CYC  阅读(289)  评论(0编辑  收藏  举报