过河(状压dp典型题)

来源:互联网 发布:软件开发培训多久 编辑:程序博客网 时间:2024/06/03 18:33

这道题最简单的dp,动态转移方程很好推,因为它是由i-s~t转移来的,所以
动态转移方程为dp[i]=min(dp[i-s~t])+q[i]
然而这个题的数据太大了。。。。。10^9
不得不考虑一些没用的操作
所以就考虑一个问题
这个题的石子数太少了,在一定的范围内,你不管怎样跳,石子数也不会增加,所以你就可以把多余的t弄掉,这样就是状压dp了,把一定的没用的范围压起来,这样数据就小点了,能过了

#include<cstdio>#include<iostream> #include<cstring>#include<algorithm>using namespace std;int n,m;int maxn=9999;int f[3000];int a[101];int q[3000];int d[101];int ans=0;int l,s,t;int main(){     scanf("%d",&l);     scanf("%d%d%d",&s,&t,&m);     for(int i=1;i<=m;i++){         scanf("%d",&a[i]);     }     sort(a+1,a+m+1);     for(int i=1;i<=m;i++)     if(a[i]-a[i-1]>t)     d[i]=(a[i]-a[i-1])%t+t;     else d[i]=a[i]-a[i-1];     for(int i=1;i<=m;i++)     {         a[i]=a[i-1]+d[i];         q[a[i]]=1;     }     for(int i=1;i<s;i++)     f[i]=99999999;     f[0]=0;     for(int i=s;i<=a[m]+t;i++)         {int w=99999;             for(int j=s;j<=t;j++)             {             if(i-j>=0)             w=min(f[i-j],w);             }             f[i]=w+q[i];         } for(int i=a[m];i<=a[m]+t;i++) maxn=min(maxn,f[i]); printf("%d ",maxn);  return 0;}
原创粉丝点击