【YbtOj】最大费用

题目链接:http://noip.ybtoj.com.cn/contest/17/problem/1

 

挺简单的一道深搜题目。

 

Saction A     输入/数据处理

有两种输入的方法,分别对应两种不同的搜索。

第一种,一次性将n个数据全部读入,然后依次枚举每个商品是买还是不买,从中选出比m小的最大价值和就行了,但是其时间复杂度为O(2n),肯定会TLE或者MLE。

第二种,分两批读入,而然是爆搜,但其时间复杂度降低到了O(n*2n/2),相比第一种,肯定划算。

既然是分两批读入,那么就是从中间一刀切。但我们不能直接写n/2,因为当n是奇数的时候很容易造成数据遗漏导致输入不完整,此刻用位运算无疑是最好的选择:n>>1。

我们定义第一次读入u个数据,第二次读入v个数据,用a数组存储商品价值,那么就有:

1 cin>>n>>m;
2 u=n>>1;
3 for(int i=1;i<=u;++i)
4     cin>>a[i];
5 dfs(0,1,u,0);
6 v=n-u;
7 for(int i=1;i<=v;++i)
8     cin>>a[i];
9 dfs(1,1,v,0);

 

Saction B     搜索

既然是水题一个,那么搜索的框架自然非常简单。

首先来确定一下搜索的终止条件。很明显当深度超过一批(有两批嘛)商品的总数时,就应该退出搜索或者说回溯,这个只用一个if判断一下就行了。在这个if当中,我们需要记载这一次搜索的结果,由于我们把商品分成了两批,所以得开个二维数组来存。定义这个数组的名称为c,其第一个下表变量表示第几批商品,第二个下标变量(准确说是这个下标变量所指向的数组位置)表示这次搜索的结果。

此时我们只用在开一个int型变量和一位数组就能把控全局。毫无疑问,这个int型的变量是用来记录这是第几批商品的,我们将其命名为bo,则这个bo的值只有0或者1(注意数组的存储是从0开始的)。

这个int型的变量解决了c数组的第一个下标变量。第二个下标变量是需要不断变化的,虽然这个变化是递增,但我们仍然能够通过一个巧妙的数组转化达到目的:一位数组b。这个数组的下标变量的含义和bo其实是一样的,只是充个数而已。

我们规定dfs函数的第一个值为bo,第二个值表示深度(我们用x表示),第三个值表示商品个数(用t表示),第四个值表示已选商品价值总和(用s表示)。

假设bo=0,我们进行第一批商品的搜索。因为每个商品只有选或者不选两种选择,所以写两个递归放在一起就行了。第一个递归里面s不变,表示不选,深度x+1.

第二个递归里面,s改变,表示选,并且s的值要加上a[x],即当前搜索的商品的价值,接着x+1。

当x>t的时候,我们需要记录本次搜素的结果,也就是把s的值放入c数组里面。为了实现存下所有的s,也就是c数组的第二个变量的递增,我们使用++b[bo],给个程序更直观:

1 int b[2];
2 if(x>t)
3 {
4     c[bo][++b[bo]]=s;
5     return;        
6 }

看到了吗,“++”表示先加在进行取数,在程序中,b[bo]的值在不断的递增,并且递增的值还是表示第一批商品的位置,也就是下标变量为bo的位置,嗯,真是机智!

 

Saction C     整合答案/输出

在整个搜索结束之后,我们得到了数组c,里面有两批商品所有的组合情况,现在需要对它们进行答案合并。

怎么合并呢?

简单,我们选择一批的数据,取出里面小于m的值,在另一组里面找出与其相加小于m的数据,然后将这样的数据汇聚在一起,选出里面的最大值即可。

我们定义答案为ans,选择第一批数据开始遍历(就是打个for循环),第一批数据的数据量为b[0]的值(很妙吧),用if判断出小于m的值。

一旦找到我们就可以开始寻找第二个数据了。但是问题来了,当第二个数据和第一个数据的量非常大时怎么办?简单,在c++里面有一个叫做upper_bound()的函数,他可以找到第一个大于待查找数值的位置,其用法如下:

1 //upper_bound(起始地址,结束地址,要查找的数值)

在这个查找之前,我们最好使用sort将第二批数据处理排序一遍,这样结合upper_bound就可以轻松解决。剩下的就是一些鸡毛蒜皮的小事了。

 

完整代码:

 1 #include<bits/stdc++.h> 
 2 using namespace std;
 3 const int maxn=1.3e6;
 4 int n,m,u,v;
 5 int a[maxn],b[2],c[2][maxn];
 6 void dfs(int bo,int x,int t,int s)
 7 {
 8     if(x>t)
 9     {
10         c[bo][++b[bo]]=s;
11         return;        
12     }
13     dfs(bo,x+1,t,s);
14     dfs(bo,x+1,t,s+a[x]);
15 }
16 int main()
17 {
18     cin>>n>>m;
19     u=n>>1;
20     for(int i=1;i<=u;++i)
21         cin>>a[i];
22     dfs(0,1,u,0);
23     v=n-u;
24     for(int i=1;i<=v;++i)
25         cin>>a[i];
26     dfs(1,1,v,0);
27     sort(c[1]+1,c[1]+b[1]+1);
28     int ans=0;
29     for(int i=1;i<=b[0];++i)
30     {
31         if(m>=c[0][i])
32         {
33             int x=upper_bound(c[1]+1,c[1]+b[1]+1,m-c[0][i])-c[1]-1;
34             ans=max(ans,c[0][i]+c[1][x]);
35         }
36     }
37     cout<<ans;
38     return 0;
39 }

 

posted on 2021-08-07 16:07  百里狂生  阅读(120)  评论(0编辑  收藏  举报

导航