滿減優惠卷(TSOJ 1552)————孤獨的餃子
先囉嗦一句,這題的來源是 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 ),還是比較慢的(所以才叫暴搜嘛)。但是測試資料範圍特別小,所以暴搜解決這個問題還是綽綽有餘的。
題目本身不難,餃子在這裡主要是給大家提供一個暴搜的模板,同時這題也是深搜的一種典型例題。