Buyer——o1背包路径查询

传送门SwustOj195

描述

哆啦A梦班级举办个party,当然吃的东西必不可少,哆啦A梦负责采购任务,他得到了一份清单,上面注明不同食品的受欢迎程度,哆啦A梦需要用一定的价钱尽可能达到的更大的受欢迎程度!例如,瓜子的受欢迎程度为20,瓜子的价钱是50元,那么如果哆啦A梦选择买瓜子,将花费50元,但受欢迎程度增加了20。为了避免食品单调性,每种食品只能买一份,不能重复购买。 现在哆啦A梦需要知道如何采购才能达到最大的受欢迎程度,你能帮助他吗?

输入

输入数据为多组,每组输入的第一行有两个正整数M和N(M<100&&N<1000),分别为哆啦A梦可以支配的钱数和清单上的可选择的物品种类。 接下来的N行每行有两个正整数,分别为每种物品的价钱和它的受欢迎程度(编号为1到N)。

输出

如果存在物品购买,那么输出的第一行为能够达到的最大的受欢迎程度。第二行为需要购买的物品的编号(如果有多种可能,输出字典序靠前的那种),空格分隔每个数字;如没有物品可以购买,输出只有一行,为数字0。

样例

  • Input
    10 4
    100 5
    5 5
    5 5
    10 10
  • Output
    10
    2 3

思路

  • 用二维存储状态,从最终结果往前推,如果dp[i][j]!=dp[i-1][j],说明取了物体i,j-=w[i],然后继续。

Code

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
#include<bits/stdc++.h>
#define INIT(a,b) memset(a,b,sizeof(a))
const int maxn=1e3+7;
using namespace std;
int m,n,w[maxn],v[maxn],dp[maxn][maxn];
int sta[maxn],tot=0;
int main() {
    while(~scanf("%d%d",&m,&n)){
        INIT(dp,0);tot=0;
        for(int i=1;i<=n;i++)
            scanf("%d%d",&w[i],&v[i]);
        for(int i=1;i<=n;i++){
            for(int j=m;j>=0;j--){
                if(w[i]>j)dp[i][j]=dp[i-1][j];
                else dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
            }
        }
        for(int i=n,j=m;i>=1&&j>=1;i--){
            if(dp[i][j]>dp[i-1][j]){
                sta[++tot]=i;
                j-=w[i];
            }
        }
        printf("%d\n",dp[n][m]);
        for(int i=tot;i>0;i--){
            printf("%d%c",sta[i]," \n"[i==1]);
        }
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值