2018年6月8號(過河)
題目描述
在河上有一座獨木橋,一只青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點: 0,1,…,L0,1,…,L (其中 LL 是橋的長度)。坐標為 00 的點表示橋的起點,坐標為 LL 的點表示橋的終點。青蛙從橋的起點開始,不停的向終點方向跳躍。一次跳躍的距離是 SS 到 TT 之間的任意正整數(包括 S,TS,T )。當青蛙跳到或跳過坐標為 LL 的點時,就算青蛙已經跳出了獨木橋。
題目給出獨木橋的長度 LL ,青蛙跳躍的距離範圍 S,TS,T ,橋上石子的位置。你的任務是確定青蛙要想過河,最少需要踩到的石子數。
輸入輸出格式
輸入格式:
第一行有 11 個正整數 L(1 \le L \le 10^9)L(1≤L≤109) ,表示獨木橋的長度。
第二行有 33 個正整數 S,T,MS,T,M ,分別表示青蛙一次跳躍的最小距離,最大距離及橋上石子的個數,其中 1 \le S \le T \le 101≤S≤T≤10 , 1 \le M \le 1001≤M≤100 。
第三行有 MM 個不同的正整數分別表示這 MM 個石子在數軸上的位置(數據保證橋的起點和終點處沒有石子)。所有相鄰的整數之間用一個空格隔開。
輸出格式:
一個整數,表示青蛙過河最少需要踩到的石子數。
輸入輸出樣例
輸入樣例#1: 復制10 2 3 5 2 3 5 6 7輸出樣例#1: 復制
2
說明
對於30%的數據, L \le 10000L≤10000 ;
對於全部的數據, L \le 10^9L≤109 。
2005提高組第二題
-----------------------------------------------------------------------
一開始那道這道題,我就開始進行暴力枚舉從後往前做,只要找到第一個符合條件的就往那跳,結果wa 0分;
麽有辦法,就看了大佬們怎麽做:
大佬做法:
我們用 f[i]表示在數軸的 i 點時所能踩石子的最少個數
if(i點有石子) f[i]=min(f[i],f[i-j]+1)
else f[i]=min(f[i],f[i-j])
然而數軸長到fai起,那麽我們就壓縮一下
先把石子位置(用數組a來存放)從小到大排序,計算兩兩石子間的距離(用數組d來存放),如果距離<=t,那麽a[i]=a[i-1]+d[i]
如果距離大於t,那麽就需要壓縮距離了,即 a[i]=a[i-1]+t+(d[i]%t)
然後還有要註意的兩點
1.它的石子沒說是已經排好序的,我看了樣例以為都是排好序的,RE了一遍。
2.註意取p的範圍,就是要在壓縮的路程後面加一個t,因為不一定最後一個點剛好是石頭最少的,可能是p+1,p+2,所以要從它轉移過來
最後附上代碼:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 int f[20000],vis[20000],a[211],b[211]; 5 int main() 6 { 7 ll l; 8 int s,t,m; 9 cin>>l; 10 cin>>s>>t>>m; 11 memset(f,0x3f,sizeof(f)); 12 memset(vis,0,sizeof(vis)); 13 a[0]=0; 14 for(int i=1;i<=m;i++) 15 cin>>a[i]; 16 a[m+1]=l; 17 sort(a,a+m+2); 18 b[0]=0; 19 int cnt=0; 20 for(int i=1;i<=m+1;i++) 21 { 22 if(a[i]-a[i-1]>=t) 23 cnt+=(a[i]-a[i-1])%t+t; 24 else 25 cnt+=a[i]-a[i-1]; 26 vis[cnt]=1; 27 } 28 vis[cnt]=0; 29 vis[0]=0; 30 f[0]=0; 31 for(int i=1;i<=cnt+t-1;i++) 32 { 33 for(int j=s;j<=t;j++) 34 if(i-j>=0) 35 f[i]=min(f[i],f[i-j]+vis[i]); 36 } 37 int ans=2100000000; 38 for(int i=cnt;i<=cnt+t-1;i++) 39 ans=min(f[i],ans); 40 cout<<ans; 41 return 0; 42 }
2018年6月8號(過河)