• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
邮票 Stamps

邮票 Stamps

P2725 [USACO3.1]邮票 Stamps

思路

​ 设\(f[i][j]\)为考虑前\(i\)个数,当面值为\(j\)时的最小邮票数,则状态转移式如下(完全背包计数):

\(f[i][j] = min(f[i - 1][j], f[i][j - coins[i]] + 1)\), 初始化\(f = inf, f[x][0] = 0\)。

那么我们便可以得到考虑前\(n\)个数,区间\([1, maxN]\) (考虑数据范围\(max(k) \times max(a_i) = 2e6\)), 的最小所需邮票数,通过枚举便可以得到答案。

复杂度\(O(n \times 2e6) \le 2e7\)

思路

#include <bits/stdc++.h>
#include <cstring>
#define rep(i, j, k) for(i64 i = j; i <= k; i ++)
#define per(i, j, k) for(int i = j; i >= k; i --)
using i64 = long long;

/*
	完全背包
	dp[i][j] = max(dp[i - 1][j], dp[i][j - v[i]] + w[i]);
*/

const int N = 3e3 + 5, MAX = 2e6 + 10;

i64 dp[MAX], v[N];

int main() {	
    int n, m;
    std::cin >> m >> n;
    
    rep(i, 1, n) {
        std::cin >> v[i];
    }

    memset(dp, 0x3f, sizeof dp);
    
    dp[0] = 0;

	rep(i, 1, n) {
		rep(j, v[i], MAX) {
			dp[j] = std::min(dp[j], dp[j - v[i]] + 1);
			// if(dp[j] > m) {
			// 	break;
			// }
		}
	}

	int ans = 0;

	for(int i = 1; i <= MAX; i ++) {
		if(dp[i] > m) {
			break;
		}
		ans ++;
	}

	std::cout << ans;
}
posted on 2023-02-06 16:15  Jack404  阅读(7)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3