搜索测试题目(1)
- 午餐费
本题目不考虑超时简单:
直接暴枚:
#include <cstdio>
#include <algorithm>
using namespace std;
int n, m, a[35], ans;
void dfs(int t, int sum) {//t为当前判断到第几个学生,sum为当前班费总和。
if (sum > m) {
return ;
}
if (t == n + 1) {
if (ans < sum) {
ans = sum;
}
return ;
}
dfs(t + 1, sum + a[t]);//让当前学生免饭钱。
dfs(t + 1, sum);//不免。
}
int main() {
while (scanf("%d %d", &n, &m) != EOF) {
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
ans = 0;
dfs(1, 0);
printf("%d\n", ans);
}
return 0;
}
交上去要S......
优化思路:
(1). 将饭钱从大到小排序。(有一点贪心策略,但不完全贪心)。
(2). 排序之后,求后缀和。(在dfs函数中有利于更加快速地判断后面的数是否还需要再次便历)。重点!!!
(3). 在dfs函数中,判断一下当前饭钱和是否大于班费。(因为后面无论怎么加都没用)。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
int n, m, a[35], ans, p, b[35];
bool cmp(int x, int y) {
return x > y;
}
void dfs(int t, int sum) {//t为当前判断到第几个学生,sum为当前班费总和。
if (sum > m) {
return ;
}
if (t == n + 1) {
if (ans < sum) {
ans = sum;
}
return ;
}
if (sum + b[t] < ans) {
return ;
}
dfs(t + 1, sum + a[t]);//让当前学生免饭钱。
dfs(t + 1, sum);//不免。
}
int main() {
while (scanf("%d %d", &n, &m) != EOF) {
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
ans = 0;
sort(a + 1, a + n + 1, cmp);
for (int i = n; i >= 1; i--) {
b[i] = b[i + 1] + a[i];
}
dfs(1, 0);
printf("%d\n", ans);
}
return 0;
}