1. 程式人生 > >[前綴和][dfs] Jzoj P5797 跳躍

[前綴和][dfs] Jzoj P5797 跳躍

nbsp script 目前 -- lds open mes 方案 ans

Description

你曾經夢想過你是電腦遊戲中的主角嗎?這個故事的主角,Branimir,現在正在做這個夢。
在Branimir的夢中,世界是由從左到右排列的N座摩天大樓組成的。對於第i座摩天大樓,我們知道摩天大樓的高度Hi和房頂金幣的數量Gi。遊戲從在任何摩天大樓上跳躍開始,由幾步組成。在每一步中,Branimir都可以從他目前所在的摩天大樓向右跳(他也有可能跳過其中的幾個),到一個高度不低於現在的摩天大樓。假如Branimir在一座摩天大樓,他可以拿這座大樓的金幣。Branimir可以在任意步數之後結束遊戲(0步也可以)通往下一關,但必須要收集至少K個金幣。
現在要求Branimir通往下一關的方案數。兩個方案當做不同當且僅當Branimir在其中一次跳過其中一座摩天大樓而另一次沒有。

Input

第一行包含兩個整數n,K
接下來n行,每行兩個整數Hi和Gi

Output

輸出一個整數,表示不同的方案數。

Sample Input

input1:
4 6
2 1
6 3
7 2
5 6
input2:
2 7
4 6
3 5
input3:
4 15
5 5
5 12
6 10
2 1

Sample Output

output1:
3
output2:
0
output3:
4

Data Constraint

對於40%的數據,1<=n<=20
對於100%的數據,1<=n<=40,1<=k<=4*10^10,1<=Hi,Gi<=10^9

Hint

第一個樣例解釋
{1,2,3},{1,4}{4}三種方案

題解

  • 這題可以用dfs過,數據比較水,200+ms,非常優秀
  • 記錄個前綴和,剪枝一下

代碼

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 int n;
 6 long long
ans,k,h[50],g[50],p[50],f[50],q[50]; 7 void dfs(int d,int last,long long sum) 8 { 9 if (d>n) 10 { 11 if (sum>=k) ans++; 12 return; 13 } 14 if (h[d]>=h[last]&&sum+g[d]>=k) ans+=f[d]; 15 else 16 if (h[d]>=h[last]&&sum+q[d]>=k) dfs(d+1,d,sum+g[d]); 17 if (sum+p[d+1]>=k) dfs(d+1,last,sum); 18 } 19 int main() 20 { 21 freopen("san.in","r",stdin); 22 freopen("san.out","w",stdout); 23 scanf("%d%lld",&n,&k); 24 for (int i=1;i<=n;i++) scanf("%lld%lld",&h[i],&g[i]); 25 f[n]=1,q[n]=g[n],p[n]=g[n],p[n+1]=0; 26 for (int i=n-1;i>0;i--) 27 { 28 f[i]=1,q[i]=0,p[i]=p[i+1]+g[i]; 29 for(int j=i+1;j<=n;j++) 30 if (h[j]>=h[i]) 31 { 32 f[i]+=f[j]; 33 if (q[j]>q[i]) q[i]=q[j]; 34 } 35 q[i]+=g[i]; 36 } 37 dfs(1,0,0); 38 printf("%lld",ans); 39 return 0; 40 }

[前綴和][dfs] Jzoj P5797 跳躍