題目傳送門:https://www.acwing.com/problem/content/167/
題目大意:有n只小貓需要坐纜車下山,但是纜車有重量限制W,每申請一個纜車需要支付1美元,問最少需要支付多少美元才能把n只小貓用纜車運下山。
(1<=N<=18,1≤Ci≤W≤10^8).
分析:最優性問題一般往三個方面思考:貪心,動態規劃和搜索。此題的N比較小,可以考慮搜索加適當優化。
對於每隻小貓我們有兩種選擇:
1.選擇放到已經申請了的纜車上
2.新申請一個纜車安放它,
對於此,搜索的過程中我們需要關心的是目前已經有幾輛纜車在安排,每輛纜車上已經裝載的重量和已經安排到第幾只小貓了。其中每輛纜車上的已經裝載重量可以用全局變量數組存儲,每次搜索回來恢復現場。
具體代碼如下:
#include<bits/stdc++.h>
using namespace std;
int n,w;
int cab[20],cat[20],ans;
void dfs(int now ,int cnt){//now 表示當前需要處理第now只貓的安排問題。cnt表示已經有cnt輛纜車在用
if(cnt > ans ) return ;//最優性剪枝,如果目前安排的纜車數量大於之前已經得出的方案中的纜車數則果斷放棄之後的安排
if(now == n+1){//當n只貓都已安排好則維護最優值
ans = min(ans, cnt);
return ;
}
//安排到現有的纜車上
for(int i = 1;i<= cnt; i++){
if(cat[now] + cab[i] <= w){// 能裝下
cab[i] += cat[now];
dfs(now+1,cnt);
cab[i] -= cat[now]; //還原現場
}
}
//新申請一個纜車
cab[cnt+1] = cat[now];
dfs(now+1 , cnt + 1);
cab[cnt+1] = 0;
}
int main(){
cin >> n >> w;
for(int i = 1;i<= n; i++){
cin >> cat[i];
}
ans = n;
//考慮輕的貓比重的貓好安排,因此將貓按重量從大到小排序,優化搜索順序
sort(cat+1,cat+1+n);
reverse(cat+1,cat+1+n);
dfs(1,0);
cout << ans;
return 0;
}