先啰嗦一句,这题的来源是 2018 NUIST 程序设计竞赛的 D 题。
题目描述
每天我们都会思考一个令人纠结的难题:晚上吃什么。你打开手机想点个外卖,发现自己有一张满减优惠券快要过期了。
你选择了一家餐厅,这家餐厅一共有 N 道菜品,价格分别是 A1, A2, ... , AN 元。只要消费满 X 元,就可以用掉这张优惠券。
你希望选择若干道 不同 的菜品,使得总价在不低于 X 元的同时尽量低。
为了用掉这张优惠券,你最少需要消费多少元?
输入描述
题目包含多组测试数据。第一行包括一个正整数 T,代表测试数据的组数。
接下来的输入,对于每组测试数据:
第一行包含两个整数 N 和 X (1 ≤ N ≤ 20, 1 ≤ X ≤ 100)
第二行包含 N 个整数 A1, A2, ... , AN (1 ≤ Ai ≤ 100)
输出描述
对于每组测试数据,输出最少的消费。如果你把 N 道菜都买了还不能达到 X 元的优惠标准,输出 -1。
样例输入
2
10 50
9 9 9 9 9 9 9 9 9 8
3 30
9 9 9
样例输出
53
-1
看完题目,不难发现这个题目实际上就是要找到满足大于等于使用优惠卷要求的最低价格。
如果想到暴力搜索,这个题目就直接秒杀了。过程就是,把种可能出现的价格全部搜索一遍,然后存储其中大于等于使用优惠卷要求的最低价格并将其输出,如果始终没找到这个最低价格,那么就输出-1,具体的实现如下。
#include<stdio.h>
int a[1000],n,m,min,x;
int inf=99999999;
void dfs(int cur,int cnt)
{
int i;
if(cnt>=x&&cnt<min)
min=cnt;
if(cur>m)
return;
dfs(cur+1,cnt+a[cur]);
dfs(cur+1,cnt);
return;
}
int main()
{
int i;
scanf("%d",&n);
while(n--)
{
min=inf;
scanf("%d %d",&m,&x);
for(i=1;i<=m;i++)
scanf("%d",&a[i]);
dfs(1,0);
if(min<inf)
printf("%d\n",min);
else
printf("-1\n");
}
return 0;
}
实际上实现暴搜每种可能出现的价格的具体步骤就是对当前菜品购买与否都搜索一次。
对于每次搜索都有两次子搜索,可以看出这种算法的复杂度是O( 2^n ),还是比较慢的(所以才叫暴搜嘛)。但是测试数据范围特别小,所以暴搜解决这个问题还是绰绰有余的。
题目本身不难,饺子在这里主要是给大家提供一个暴搜的模板,同时这题也是深搜的一种典型例题。