【luogu P1833】樱花——混合背包

题目链接:P1833 樱花

思路: 显然将时间看作容量, C i C_i Ci看作价值, T i T_i Ti看作大小, P i P_i Pi看作个数( P i = 0 P_i=0 Pi=0可以取无限个,视作完全背包),可以转化成混合背包求解。

T = T 2 − T 1 T=T_2-T_1 T=T2T1,分开处理:

P i = 0 P_i=0 Pi=0 P i × T i ≤ T P_i\times T_i\leq T Pi×TiT(可以随便取而不会个数不够)时看作完全背包

其他情况下当作多重背包,数据量比较小可以用二进制优化转01背包 O ( T Σ log ⁡ P i ) O(T\Sigma \log P_i) O(TΣlogPi)或者单调队列 O ( T N ) O(TN) O(TN)

​代码:
这里提供一种单调队列优化的写法。

#include <iostream>
#include <algorithm>
#include <string>
#include <stdio.h>
#include <set>
#include <map>
#include <stack>
#include <iomanip>
#include <numeric>
#include <cmath>
#include <functional>
#include <numeric>
#include <ctime>
#include <random>
#include <queue>
#include <vector>
#include <unordered_map>
#define sqr(x) ((x) * (x))
#define fo(x) for(int i=0;i<x;i++)
#define _for(a,b,c) for(int a=b;a<c;a++)
#define _rep(a,b,c) for(int a=b;a<=c;a++)
#define ll long long
#define inf 0x3f3f3f3f
#define endl '\n'
#define ull unsigned long long
#define int long long
#define MAXN 1000005
#define MAXM 26
#define mod 998244353
using namespace std;
int dp[1005];
int mp[1005];
int q[1005];
void solve() {
	int h1, m1, h2, m2;
	char c;
	int n;
	cin >> h1 >> c >> m1;
	cin >> h2 >> c >> m2;
	int V = (h2 - h1) * 60 + m2 - m1;
	cin >> n;
	fo(n) {
		int w, v, s;
		cin >> v >> w >> s;
		if (s == 0 || s * v >= V) {
			for (int i = v; i <= V; i++) {
				dp[i] = max(dp[i], dp[i - v] + w);
			}
		}
		else {
			for (int ind = 0; ind < v; ind++) {
				int head = 0, tail = 0;
				for (int i = ind; i <= V; i += v) {
					int temp = dp[i] - i / v * w;
					while (head < tail && q[tail - 1] <= temp) {
						tail--;
					}
					if (mp[head] < i - s * v) {
						head++;
					}
					mp[tail] = i;
					q[tail++] = temp;
					dp[i] = q[head] + i / v * w;
				}
			}
		}
	}
	cout << dp[V] << endl;
}
signed main() {
	cin.tie(nullptr)->sync_with_stdio(0);
	int t = 1;
	//cin >> t;
	while (t--) {
		solve();
	}
}
  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值