【♂Not The Triumph♂O(∩_∩)O哈哈~But The Struggle♂】

竞赛决不是捷径,它只是另一种艰辛的生活方式。得到与失去,只有时间会去评判;成功与失败,只有历史能去仲裁。我不会永远成功,正如我不会永远失败一样

  C++博客 :: 首页 :: 联系 ::  :: 管理
  6 Posts :: 239 Stories :: 25 Comments :: 0 Trackbacks

常用链接

留言簿(7)

我参与的团队

搜索

  •  

积分与排名

  • 积分 - 108444
  • 排名 - 229

最新评论

阅读排行榜

评论排行榜

【问题描述】
在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。

题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数

【输入文件】
输入文件river.in的第一行有一个正整数L(1 <= L <= 109),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1 <= S <= T <= 10,1 <= M <= 100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

【输出文件】
输出文件river.out只包括一个整数,表示青蛙过河最少需要踩到的石子数。

【样例输入】
10
2 3 5
2 3 5 6 7

【样例输出】
2

【数据规模】
对于30%的数据,L <= 10000;
对于全部的数据,L <= 10^9。

分析:
  动态规划,需要状态压缩。
  状态:F[i] 跳到距离i处碰到的最少的石子数。

  状态转移方程:F[i]=min{ F[i-k] } + F[i] (S<=k<=T i-k>=0)
  边界条件:F[i]=1 i处有石子
 
  目标结果:min{ F[k] } (L+1<=k<=L+T-1)

  状态压缩
  由于L最大为10^9,直接线性递推会超时。发现石子数很少,这意味着路径上有许多很长的空白段。我们可以把长度大于S*T的空白段都缩小到S*T,这样最长只有10090了。


【参考程序】:

#include<cstring>
#include
<cstdio>
#include
<iostream>
#define maxint 0xFFFFFFF;
using namespace std;

int F[10100],stone[110
];
int
 n,m,s,t,ans;
int cmp(const void *s,const void *
t)
{
    
int i=*(int *)s,j=*(int *
)t;
    
return i-
j;
}
void
 reduce()
{
    
int p=s*
t,k;
    stone[
0]=0; stone[m+1]=
n;
    memset(F,
0,sizeof
(F));
    
for (int i=1;i<=m+1;i++
)
    {
        
if (stone[i]-stone[i-1]>
p)
        {
            k
=stone[i]-stone[i-1]-
p;
            
for (int j=i;j<=m+1;j++
)
                stone[j]
-=
k;
            stone[i]
=stone[i-1]+
p;
        }
        F[stone[i]]
=1
;
    }
    n
=stone[m+1
];
}
void
 dp()
{
    
int
 mins;
    
for (int i=1;i<=n+t-1;i++
)
    {
        mins
=
maxint;
        
for (int j=s;j<=t;j++
)
            
if (i-j>=0 && F[i-j]<
mins)
                mins
=F[i-
j];
        F[i]
+=
mins;
    }
}
int
 main()
{
    scanf(
"%d",&
n);
    scanf(
"%d%d%d",&s,&t,&
m);
    
for (int i=1;i<=m;i++) scanf("%d",&
stone[i]);
    
if (s==
t)
    {
        ans
=0
;
        
for (int i=1;i<=m;i++
)
            
if (stone[i]%s==0) ans++
;
        printf(
"%d\n"
,ans);
        exit(
0
);
    }
    qsort(stone
+1,m,sizeof(int
),cmp);
    reduce();
    dp();
    ans
=
maxint;
    
for (int i=n+1;i<=n+t-1;i++
)
        
if (ans>F[i]) ans=
F[i];
    printf(
"%d\n"
,ans);
    
return 0
;
}
posted on 2009-08-15 11:30 开拓者 阅读(747) 评论(0)  编辑 收藏 引用 所属分类: 动态规划&背包NOIP历届题目

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理