九度 1531:货币面值(01背包)

本文介绍了一个游戏中的财政问题——寻找无法通过现有纸币面额组合而成的最小面额。通过将此问题转换为背包问题的变形,利用动态规划求解,并提供了一段C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

小虎是游戏中的一个国王,在他管理的国家中发行了很多不同面额的纸币,用这些纸币进行任意的组合可以在游戏中购买各种装备来提升自己。有一天,他突然很想知道这些纸币的组合不能表示的最小面额是多少,请聪明的你来帮助小虎来解决这个财政问题吧

 

思路

1. 面值最小额度, 枚举的话时间复杂度为 o(n^3). 但思考一下就会发现其实这是背包问题恰好装满的变形题

2. 背包问题恰好装满是在朴素背包问题的基础上初始化 dp[0] = 0, dp[i] = 负无穷. 这样就会使得不能恰好装满的容量都是负无穷

3. 下面的代码设置的是 int dp[], 其实设置成 bool dp[] 也是可以的

 

代码

#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;

const int INF = 10005;
int dp[10010];
int money[110];

void dodp(int n) {
    memset(dp, 0x80, sizeof(dp));
    
    dp[0] = 0;
    for(int i = 0; i < n; i ++) {
        for(int v = INF; v >= 0; v --) {
            if(v >= money[i])
                dp[v] = max(dp[v-money[i]]+money[i], dp[v]);
        }
    }

    for(int i = 0; i < INF; i++) {

        if(dp[i] < 0) {
            cout << i << endl;    
            break;
        }
            
    }
}

int main() {
    
    int n;
    while(scanf("%d", &n) != EOF) {
        for(int i = 0; i < n; i ++)
            scanf("%d", money+i);
        dodp(n);
    }
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值