搜索测试题目(1)

  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;
}
posted @ 2021-03-13 16:59  cqbz  阅读(21)  评论(0编辑  收藏  举报