习题:san(搜索)
题目:
题目描述
时间:1000ms
空间64MB
游戏世界中有N个楼从左到右排列,从左到右编号为1到N,第i幢楼的高度为Hi,楼上的金币数为Gi,游戏可以从任意一个楼开始且包涵几步。每一步玩家可以从当前位置向右跳(可以跳过一些楼)但必须跳到不低于当前楼的高度的楼上。他到了楼上后,可以得到楼上的金币。他可以在跳任意步(可以是零步)后结束游戏,但是要保证收到的金币数要大于等于K,现在想知道共有多少不同的种方案满足游戏。两个方案不同是指至少有一个楼不一样的方案。
输入格式
第一行两个数N (1 ≤ N ≤ 40) and K (1 ≤ K ≤ 4·10^10 )
接下来N行,每行两个正整数,第i行用Hi和Gi表示第i个楼的高度和上面的金币。 (1 ≤ Hi, Gi ≤ 109 )
输出格式
一行一个数,表示方案总数。
样例输入
4 6
2 1
6 3
7 2
5 6
样例输出
3
思路:
看到这题n这么小,第一反应就是搜索,再看了看题目的部分分,发现如果n<=20,就有50分,那么这50分应该可以爆搜拿满,
考虑对搜索进行优化,之后自然就想到将h数组和g数组分半,之后先对前一半的数组进行求解,再对后一半的数组进行求解,
用数组将两次搜索的值记录下来,最后再合并。
给出代码以辅助理解
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
using namespace std;
void read(long long &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(long long x)
{
if(x<0)
{
putchar('-');
write(-x);
return;
}
if(x<10)
putchar(x+'0');
else
{
write(x/10);
putchar(x%10+'0');
}
}
long long ans;
long long n,k;
long long h[45];
long long g[45];
vector<long long> l[45];
vector<long long> r[45];
vector<long long> hou;
void jump_to_left(long long f_now,long long f_last,long long s)
{
if(f_now==n/2)
{
long long f_index=lower_bound(hou.begin(),hou.end(),f_last)-hou.begin();
l[f_index].push_back(s);
return;
}
jump_to_left(f_now+1,f_last,s);
if(h[f_now]>=f_last)
jump_to_left(f_now+1,h[f_now],s+g[f_now]);
return;
}
void jump_to_right(long long f_now,long long f_first,long long f_last,long long s)
{
if(f_now==n)
{
long long f_index=lower_bound(hou.begin(),hou.end(),f_first)-hou.begin();
r[f_index].push_back(s);
return;
}
jump_to_right(f_now+1,f_first,f_last,s);
if(h[f_now]>=f_last)
{
int k;
if(f_first==0)
k=h[f_now];
else
k=f_first;
jump_to_right(f_now+1,k,h[f_now],s+g[f_now]);
}
return;
}
int main()
{
read(n);
read(k);
for(int i=0;i<n;i++)
{
read(h[i]);
read(g[i]);
hou.push_back(h[i]);
}
hou.push_back(0);
sort(hou.begin(),hou.end());
jump_to_left(0,0,0);
jump_to_right(n/2,0,0,0);
for(int i=0;i<hou.size();i++)
sort(r[i].begin(),r[i].end());
for(int i=0;i<(int)hou.size();i++)
{
for(int z=0;z<l[i].size();z++)
{
long long it=l[i][z];
ans+=r[0].end()-lower_bound(r[0].begin(),r[0].end(),k-it);
for(int j=i;j<hou.size();j++)
{
ans+=r[j].end()-lower_bound(r[j].begin(),r[j].end(),k-it);
}
}
}
write(ans);
return 0;
}

浙公网安备 33010602011771号