您的位置:首页 > 其它

Tyvj1059

2017-09-06 14:57 127 查看
题目链接

分析:

网上没有特别好的题解,所以还是要靠自己啊

直接dp并不困难

方程

i位置没有石头 f[i]=min{f[j]} i-t<=j<=i-s

i位置有石头 f[i]=min{f[j]}+1 i-t<=j<=i-s

然而,想要直接开下L的数组肯定是不现实的,

我们就要考虑优化了

如果s==t,那我们只用简单的计算一下就好了

要是s!=t,就需要一个巧妙的优化了

如果有一大段没有石头,那么我们一个一个转移肯定有点浪费的

我们要是能找到一段没有石头而且能够直接忽略的规定距离

(忽略的意思是不管s,t为何值都可以通过某种跳法恰好通过)

这样我们就可以直接删除这段距离

我们找到的这段距离是100

为什么是100呢

观察一下s,t的范围,只有10

很显然,当s和t的差值较小的时候,能够恰好走到100就比较困难了

那我们可以看一下所有的情况

s=1,t=2

100=100*1

s=2,t=3

100=2*50

s=3,t=4

100=5*(3+3+3+3+4+4)

s=4,t=5

100=20*5

s=5,t=6

100=20*5

s=6,t=7

100=5*(6+7+7)

s=7,t=8

100=2*(7+7+7+7+7+7+8)

s=8,t=9

100=4*(8+8+9)

s=9,t=10

100=10*10

真的都可以达到

这样的话,如果两块石头之间的差距是100(或者是100的倍数)

我们就可以直接忽略

这样数组的大小就缩小到了10000(100块石头,两块石头之间最多相聚100)

这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

int L,s,t;
int a[110];
int n;
int f[100010];
int p[100010];

void doit()
{
int i,j,k;
a[++n]=L;
for (i=1;i<=n;i++)
if (a[i]-a[i-1]>100)
{
int r=a[i]-a[i-1];
r/=100;
for (j=i;j<=n;j++)
a[j]-=r*100;
}
for (i=1;i<n;i++) p[a[i]]=1;
memset(f,0x33,sizeof(f));
f[0]=0;
for (i=1;i<=a
;i++)
for (j=i-t;j<=i-s;j++)
if (j>=0) f[i]=min(f[i],f[j]+p[i]);
printf("%d",f[a
]);
}

int main()
{
scanf("%d%d%d",&L,&s,&t);
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
if (s==t)
{
int ans=0;
for (int i=1;i<=n;i++) if (a[i]%s==0) ans++;
printf("%d",ans);
return 0;
}
else doit();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: