算法搜索启发式搜索
POJO启发式搜索
题目描述
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
输入格式
第一行有 个整数 ()和 (),用一个空格隔开, 代表总共能够用来采药的时间, 代表山洞里的草药的数目。
接下来的 行每行包括两个在
到 之间(包括 和 )的整数,分别表示采摘某株草药的时间和这株草药的价值。
输出格式
输出在规定的时间内可以采到的草药的最大总价值。
样例 #1
样例输入 #1
样例输出 #1
提示
【数据范围】
【题目来源】
NOIP 2005 普及组第三题
题解
- 启发式函数的作用是基于已有的信息,对搜索的每一个分支选择都做估价,进而选择分支。简单来说,启发式搜索就是对取和不取都做分析,从中选取更优解或删去无效解。
- 贪心选择物品:从第
个物品开始依次选择物品。对于每个物品 ,如果其所需的时间 小于或等于当前剩余时间 ,则选择该物品并扣除相应的时间 ,并将该物品的价值加到总价值 中,即 。
- 部分选择物品:如果某个物品的时间需求 大于剩余时间 ,则不能完整选择该物品。但是我们可以选择一部分时间来获取部分价值。这个部分价值根据该物品的性价比
来计算,即 。
- 完全选择物品的情况:如果循环结束且剩余时间足够支撑完整的物品选择,则返回累计的总价值
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| #include <iostream> #include <algorithm>
using namespace std; const int N = 105; int n, m, ans;
struct Node { int a, b; double f; } node[N];
bool operator<(Node p, Node q) { return p.f > q.f; }
int f(int thinkn, int times) { int tot = 0; for (int i = 1; thinkn + i <= n; i++) if (times >= node[thinkn + i].a) { times -= node[thinkn + i].a; tot += node[thinkn + i].b; } else return (int)(tot + times * node[thinkn + i].f); return tot; }
void work(int thinkn, int times, int value) { ans = max(ans, value); if (thinkn > n) return; if (f(thinkn, times) + value > ans) work(thinkn + 1, times, value); if (node[thinkn].a <= times) work(thinkn + 1, times - node[thinkn].a, value + node[thinkn].b); }
int main() { cin >> m >> n; for(int i = 1; i <= n ; i ++ ) { cin >> node[i].a >> node[i].b; node[i].f = 1.0 * node[i].b / node[i].a; } sort(node + 1, node + 1 + n); work(1, m, 0); cout << ans; return 0; }
|