习题: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;
}

 

posted @ 2019-07-27 19:58  loney_s  阅读(157)  评论(0)    收藏  举报