洛谷 P1052 過河

題目描述

在河上有一座獨木橋,一隻青蛙想沿着獨木橋從河的一側跳到另外一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。因爲橋的長度和青蛙一次跳過的距離都是正整數,咱們能夠把獨木橋上青蛙可能到達的點當作數軸上的一串整點:\(0,1,…,L\)(其中\(L\)是橋的長度)。座標爲\(0\)的點表示橋的起點,座標爲\(L\)的點表示橋的終點。青蛙從橋的起點開始,不停的向終點方向跳躍。一次跳躍的距離是\(S\)\(T\)之間的任意正整數(包括\(S,T\))。當青蛙跳到或跳過座標爲\(L\)的點時,就算青蛙已經跳出了獨木橋。ios

題目給出獨木橋的長度\(L\),青蛙跳躍的距離範圍\(S,T\),橋上石子的位置。你的任務是肯定青蛙要想過河,最少須要踩到的石子數。git

輸入輸出格式

輸入格式:優化

第一行有\(1\)個正整數\(L(1 \le L \le 10^9)\),表示獨木橋的長度。spa

第二行有\(3\)個正整數\(S,T,M\),分別表示青蛙一次跳躍的最小距離,最大距離及橋上石子的個數,其中\(1 \le S \le T \le 10\),\(1 \le M \le 100\)code

第三行有\(M\)個不一樣的正整數分別表示這\(M\)個石子在數軸上的位置(數據保證橋的起點和終點處沒有石子)。全部相鄰的整數之間用一個空格隔開。get

輸出格式:string

一個整數,表示青蛙過河最少須要踩到的石子數。it

輸入輸出樣例

輸入樣例#1:io

10
2 3 5
2 3 5 6 7

輸出樣例#1:class

2

說明

對於\(30\%\)的數據,\(L \le 10000\)

對於所有的數據,\(L \le 10^9\)

思路:不加優化的話會重複計算好多的多餘的東西。因此咱們能夠把這樣一段段沒用的東西減掉,怎麼減呢,這就是狀壓的另外一種實現。由於\(s\)\(t\)都小於等於\(10\),因此求得\(1-10\)的最小公倍數是\(2520\),而當兩個點相距\(2520\)時,減掉也不會有影響。這裏有幾種具體的實現方法,但好像只有我下面呈現的這種比較好寫。注意輸入數據不必定有序,因此要先打一個快排。

代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define mod 2520
#define maxn 400001
using namespace std;
inline int qread() {
  char c=getchar();int num=0,f=1;
  for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
  for(;isdigit(c);c=getchar()) num=num*10+c-'0';
  return num*f;
}
int m,s,t,l,ans,a[101],sz[101],vis[maxn],f[maxn];
int main() {
  l=qread(),s=qread(),t=qread(),m=qread();
  for(int i=1;i<=m;++i) a[i]=qread();
  sort(a+1,a+1+m);
  for(int i=1;i<=m;++i)
    sz[i]=(a[i]-a[i-1])%2520;
  for(int i=1;i<=m;++i) {
    a[i]=a[i-1]+sz[i];
    vis[a[i]]=1;
  }
  l=a[m];
  ans=m;
  for(int i=0;i<=l+t;++i) f[i]=m;
  f[0]=0;
  for(int i=1;i<=l+t;++i) {
    for(int j=s;j<=t;++j) {
      if(i-j>=0)
        f[i]=min(f[i],f[i-j]);
      f[i]+=vis[i];
    }
  }
  for(int i=l;i<l+t;++i)
    ans=min(ans,f[i]);
  cout<<ans<<'\n'; 
  return 0;
}
相關文章
相關標籤/搜索