hihoCoder184——滿減優惠
阿新 • • 發佈:2019-01-30
題目1 : 滿減優惠
時間限制:10000ms 單點時限:1000ms 記憶體限制:256MB描述
最近天氣炎熱,小Ho天天宅在家裡叫外賣。他常吃的一家餐館一共有N道菜品,價格分別是A1, A2, ... AN元。並且如果消費總計滿X元,還能享受優惠。小Ho是一個不薅羊毛不舒服斯基的人,他希望選擇若干道不同的菜品,使得總價在不低於X元的同時儘量低。
你能算出這一餐小Ho最少消費多少元嗎?
輸入
第一行包含兩個整數N和X,(1 <= N <= 20, 1 <= X <= 100)
第二行包含N個整數A1, A2, ..., AN。(1 <= Ai <= 100)
輸出
輸出最少的消費。如果小Ho把N道菜都買了還不能達到X元的優惠標準,輸出-1。
好久沒有寫題了,不得不說csdn這個編輯頁面真的是越改越差。
這道題我用了動規跟dfs做,結果dfs只有70分,我也不太懂,都po出來吧。動規好理解,就是01揹包問題,這裡再梳理一下這型別的問題。
大概意思就是:f [ I, j ] = max { ( f [ i-1, j - Wi ] + Pi)(其中 j >= Wi ) , f [ I-1, j ] } :f代表揹包裡有 I 個物體,其重量為 j 時的價值,其中每個物品的重量為Wi,價值為Pi。一般遍歷就是從 i : 0-->n,j :0 --> sum(Wi),(初始值都為零)也視情況而定。
int main(){ int sum = 0; cin>>n>>x; int dp[200] = {0}; for(int i = 0; i<n; i++){ scanf("%d", &a[i]); sum += a[i]; } int d = sum-x; if(d < 0) printf("-1\n"); else if(d == 0) printf("%d\n", x); else{ int out = -1; for(int i = 0; i<n; i++){ for(int j = d; j>=0; j--){ dp[j] = max(dp[j], dp[j-a[i]]+a[i]); out = max(dp[j], out); } } printf("%d", out); } return 0; }
因為這個對物品的個數不敏感,所以不用dp[i,j],只用dp[i]即可。先將所有的物體全放進去,然後在物品總重大於x(d>0)的情況下能拿多少就拿多少。之前一直想著先動規出在總重小於x的時候拿到最大,然後再加上任意其他看最小,可行性很低,換個思路就簡單多了。
dfs我也不知道哪裡錯了,就是排列組合的說。
int a[200] = {0};
int n, x;
int dfs(int b, int sum){
int out = 1000000000;
if(sum >= x){
return sum;
}
for(int i = b+1; i<n; i++){
out = min(out, dfs(i, sum+a[i]));
}
return out;
}
int _main() {
int sum = 0;
int out = 1000000000;
cin>>n>>x;
for(int i = 0; i<n; i++){
scanf("%d", &a[i]);
sum += a[i];
}
if(sum < x){
printf("-1\n");
return 0;
}
sort(a, a+n, [](int x1, int x2){return x1 < x2;});
for(int i = 0; i<n; i++){
out = min(out, dfs(i, a[0]));
}
printf("%d\n", out);
return 0;
}