P1164 小A点菜——记忆化搜索,递推与递归
题目背景
uim 神犇拿到了 uoi 的 ra(镭牌)后,立刻拉着基友小 A 到了一家……餐馆,很低端的那种。
uim 指着墙上的价目表(太低级了没有菜单),说:“随便点”。
题目描述
不过 uim 由于买了一些书,口袋里只剩
餐馆虽低端,但是菜品种类不少,有
小 A 奉行“不把钱吃光不罢休”的原则,所以他点单一定刚好把 uim 身上所有钱花完。他想知道有多少种点菜方法。
由于小 A 肚子太饿,所以最多只能等待
输入格式
第一行是两个数字,表示
第二行起
输出格式
一个正整数,表示点菜方案数,保证答案的范围在 int 之内。
输入输出样例 #1
输入 #1
4 4 1 1 2 2
输出 #1
3
说明/提示
2020.8.29,增添一组 hack 数据 by @yummy
超时解法
for循环暴力&无记忆
#include <bits/stdc++.h> using namespace std; int a[1001]; int mycount=0; int n,m; void dfs(int index,int money) { if(money==0) { mycount++; return; } for (int i=index;i<n;i++) { dfs(i+1,money-a[i]); } } int main() { cin>>n>>m; for (int i=0;i<n;i++) { cin>>a[i]; } dfs(0,m); cout<<mycount; }
题解
最小事件:选择/不选择;记忆化搜索
#include <iostream> #include <cstring> using namespace std; const int MAXN = 105; const int MAXM = 10010; int a[MAXN]; int n, m; int mem[MAXN][MAXM]; // 记忆化搜索函数 int dfs(int index, int money) { // 如果剩余钱为 0,说明刚好花完,返回 1 if (money == 0) { return 1; } // 如果剩余钱小于 0 或者已经遍历完所有菜品,返回 0 if (money < 0 || index == n) { return 0; } // 如果已经计算过该状态,直接返回结果 if (mem[index][money] != -1) { return mem[index][money]; } // 不选择当前菜品 int res = dfs(index + 1, money); // 选择当前菜品 res += dfs(index + 1, money - a[index]); // 记录当前状态的结果 mem[index][money] = res; return res; } int main() { cin >> n >> m; for (int i = 0; i < n; i++) { cin >> a[i]; } // 初始化记忆化数组 memset(mem, -1, sizeof(mem)); cout << dfs(0, m) << endl; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了