P1164 小A点菜【dp】

P1164 小A点菜

提交 43.03k
通过 24.37k
时间限制 1.00s
内存限制 125.00MB
题目提供者 洛谷
难度 普及-
历史分数100

提交记录

查看题解

标签

洛谷原创
 
查看算法标签
进入讨论版

相关讨论

 
查看讨论

推荐题目

 
查看推荐
 

展开

题目背景

uim神犇拿到了uoira(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种。

uim指着墙上的价目表(太低级了没有菜单),说:“随便点”。

题目描述

不过uim由于买了一些辅(e)辅(ro)书,口袋里只剩MMM元(M≤10000)(M \le 10000)(M10000)。

餐馆虽低端,但是菜品种类不少,有NNN种(N≤100)(N \le 100)(N100),第iii种卖aia_iai(ai≤1000)(a_i \le 1000)(ai1000)。由于是很低端的餐馆,所以每种菜只有一份。

小A奉行“不把钱吃光不罢休”,所以他点单一定刚好吧uim身上所有钱花完。他想知道有多少种点菜方法。

由于小A肚子太饿,所以最多只能等待111秒。

输入格式

第一行是两个数字,表示NM

第二行起N个正数ai(可以有相同的数字,每个数字均在1000以内)。

输出格式

一个正整数,表示点菜方案数,保证答案的范围在int之内。

输入输出样例

输入 #1
4 4
1 1 2 2
输出 #1
3

思路:
  用f[i][j]来表示取到第i个物品、有j块钱能吃到的方案数。
  在每次转移时,有三种情况:
  1、j == w[i], 此时f[i][j]等于选了i-1件的有j块钱的方案数+1.
  2、j > w[i], 此时由于钱是富足的,所以可以拿f[i-1][j]+f[i-1][j-w[i]]的方案数
  3、j < w[i], 此时由于钱不够了,所以拿不了,方案数为f[i-1][j].

  因为和上一个物品状态关联不大。题解把三个情况总结到一起了,方程写成了f[j-w[i]],在nm比较大的时候可以用上。

 1 #include 
 2 #define dbg(x) cout << #x << "=" << x << endl
 3 
 4 using namespace std;
 5 typedef long long LL;
 6 const int maxn = 100 + 7;
 7 
 8 int f[maxn][10007];
 9 int w[maxn];
10 
11 namespace _buff {
12 
13 const size_t BUFF = 1 << 19;
14 char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
15 char getc() {
16     if (ib == ie) {
17         ib = ibuf;
18         ie = ibuf + fread(ibuf, 1, BUFF, stdin);
19     }
20     return ib == ie ? -1 : *ib++;
21 }
22 
23 }
24 
25 int read() {
26     using namespace _buff;
27     int ret = 0;
28     bool pos = true;
29     char c = getc();
30     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
31         assert(~c);
32     }
33     if (c == '-') {
34         pos = false;
35         c = getc();
36     }
37     for (; c >= '0' && c <= '9'; c = getc()) {
38         ret = (ret << 3) + (ret << 1) + (c ^ 48);
39     }
40     return pos ? ret : -ret;
41 }
42 
43 int main()
44 {
45     int n,m;
46     scanf("%d %d",&n,&m);
47     for(int i = 1; i <= n; ++i) {
48         scanf("%d",&w[i]);
49     }
50     int ans = 0;
51     for(int i = 1; i <= n; i++) {
52         for(int j = 0; j <= m; j++) {
53             if(j == w[i]) {
54                 f[i][j] = f[i-1][j] + 1;
55             }
56             else if(j > w[i]) {
57                 f[i][j] = f[i-1][j] + f[i-1][j-w[i]];
58             }
59             else if(j < w[i]) {
60                 f[i][j] = f[i-1][j];
61             }
62         }
63     }
64 
65     printf("%d\n",f[n][m]);
66     return 0;
67 }
View Code

 

你可能感兴趣的:(P1164 小A点菜【dp】)