[前缀和][dfs] Jzoj P5797 跳跃

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 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9464026.html
今日推荐