solution1(通过65%)
#include<iostream>
using namespace std;
int n, m, flag = 0, ans = 31;
double w[35];
void dfs(int index, double curW, int cnt){
if(curW >= m || index >= n || (flag && cnt >= ans)){
if(curW == m && index <= n) {
flag = 1;
if(cnt < ans) ans = cnt;
}
return;
}
if(w[index] + curW <= m) dfs(index + 1, curW + w[index], cnt);
if(w[index] / 2 + curW <= m && ans > cnt + 1) dfs(index + 1, curW + w[index] / 2, cnt + 1);
dfs(index + 1, curW, cnt);
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++){
scanf("%lf", w + i);
}
dfs(0, 0, 0);
if(flag) printf("%d", ans);
else printf("-1");
return 0;
}
solution2
- 用后缀和剪枝,若已有重量加上后缀和任不小于m则不可行
- 从大到小枚举,更快的过滤错误答案
#include<iostream>
#include<algorithm>
using namespace std;
int n, m, ans = 31;
double w[35], rearSum[35] = {0};
void dfs(int index, double curW, int cnt){
if(rearSum[index] + curW < m || curW >= m || index >= n || cnt >= ans){
if(curW == m && index <= n && cnt < ans) ans = cnt;
return;
}
if(w[index] + curW <= m) dfs(index + 1, curW + w[index], cnt);
if(w[index] / 2 + curW <= m && ans > cnt + 1) dfs(index + 1, curW + w[index] / 2, cnt + 1);
dfs(index + 1, curW, cnt);
}
bool cmp(int a, int b){
return a > b;
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++){
scanf("%lf", w + i);
}
sort(w, w + n, cmp);
for(int i = n - 1; i >= 0; i--){
rearSum[i] = w[i] + rearSum[i + 1];
}
dfs(0, 0, 0);
if(ans != 31) printf("%d", ans);
else printf("-1");
return 0;
}