P1052 过河

题意:给出桥的长度,给出石头个数;给出所有石头的位置

  背景:有一只不喜欢跳石头的青蛙想要跳尽量少的石头跳到桥对岸 (注:是尽量不跳石头,而不是一定得跳石头) 

      一开始做这道题的时候,就是以为一定得跳石头才能过,然后以为题意出错(因为数据范围不允许这样跳)

        后来才知道原来是什么地方都可以跳

  思路:题意范围达到1e9;所以直接dp会超时;

    但是,我们可以通过改石头位置来改总长度以此优化复杂度;

      题目给出石头个数只有100个,青蛙的跳跃范围是(1,10)

        假设有两个石头一个坐标是1,一个是100,那么这两石头之间,有很多不会跳到石头的但是必须跳到的点

          所以我们可以将这部分省略,因为这段区间不影响答案

            那么怎么省略掉呢,自然是按最大的跳跃距离来跳离这段没有石头的点

              于是我们可以直接将这段距离去掉,用数学化的语句来表达就是: (a[i]-a[i-1])%t+t;

                 最后+t是有原因的,因为不加的话,青蛙距离下一个点的位置就是一个小于t的距离

                    然后这位置可能导致往前一定跳到石头(如果不在这个位置可能就不跳到石头)

                      所以我们多加一段t的距离去dp,这样就可以保证得到最优答案;

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int inf=0x3f3f3f3f;
 4 const int maxn=2e4+10;
 5 int dp[maxn];
 6 int stone[maxn];
 7 int a[maxn];
 8 int main()
 9 {
10     int len;
11     scanf("%d",&len);
12     int s,t,n;
13     scanf("%d%d%d",&s,&t,&n);
14     a[0]=0;
15     for(int i=1;i<=n;i++){
16         scanf("%d",&a[i]);
17     }
18     a[n+1]=len;
19     sort(a,a+n+2);
20     int base=0;
21     for(int i=1;i<=n+1;i++){
22         if(a[i]-a[i-1]>t){
23             base+=(a[i]-a[i-1])%t;
24         }
25         else base+=a[i]-a[i-1];
26         stone[base]=1;
27     }
28     stone[base]=0;stone[0]=0;
29     memset(dp,inf,sizeof(dp));
30     dp[0]=0;
31     for(int i=1;i<=base+t-1;i++){
32         for(int j=s;j<=t;j++){
33             if(i-j>=0)
34                 dp[i]=min(dp[i],dp[i-j]+stone[i]);
35         }
36     }
37 //    for(int i=0;i<=base;i++)
38 //        printf("%d ",stone[i]);
39 //    printf("\n");
40 //    for(int i=1;i<=base;i++)
41 //        printf("%d ",dp[i]);
42 //    printf("\n");
43     int ans=0x3f3f3f3f;
44     for(int i=base;i<=base+t-1;i++)
45         ans=min(ans,dp[i]);
46     printf("%d\n",ans);
47     return 0;
48 }
View Code

 

posted @ 2020-03-23 12:34  古比  阅读(151)  评论(0编辑  收藏  举报