01背包变种(7的倍数)

U197241 ご注文はうさぎですか?

题目描述

这是一道和兔子有关的签到题:

在这里插入图片描述

かふうちの是一个可爱的初中生,虽然性格有些冷淡,但是不讨厌ココア…!?精通咖啡,并且能干可靠。

今天ちの在梦境中看见了一群野兔子,棉花糖般的兔子们每一只都有一个甜度 a i {a_i} ai 。ちの想从中挑选出一些兔子,使得它们的甜度和是 7 {7} 7 的倍数。请问能获得的最大甜度和是多少。

当然,这个问题可能太简单了,所以ココア降临了:ココア亲吻过的兔子会获得”祝福”,当ちの选择这只兔子之后,她将会减少 b i {b_i} bi点精神力。ちの最初有 H {H} H 点精神力,当精神力小于 0 {0} 0 时,她将会被ココア吃掉(((

ちの想知道怎么样才能完成挑选甜度和为 7 {7} 7 的倍数的兔子,甜度和最大的同时还不会被吃掉。


输入格式

第一行包含两个正整数 n ( 1 < = n < = 1 0 4 ) {n(1<=n<=10^4)} n(1<=n<=104) H ( 1 < = H < = 1 0 3 ) {H(1<=H<=10^3)} H(1<=H<=103)
第二行包含 n {n} n 个非负整数 a i ( 0 < = a i < = 1 0 9 ) {a_i(0<=a_i<=10^9)} ai(0<=ai<=109),表示每只兔子的甜度。
第二行包含 n {n} n 个非负整数 b i ( 0 < = b i < = 10 ) {b_i(0<=b_i<=10)} bi(0<=bi<=10) ,表示每只兔子对精神力的作用。


输出格式

输出单行,包含一个整数 S {S} S,表示挑选甜度和为 7 {7} 7 的倍数的兔子,且不会被吃掉的最大甜度和。


输入输出样例

输入 #1

10 10
9 3 7 3 6 4 4 5 9 9
0 1 1 1 1 0 0 1 0 0

输出 #1

56

输入 #2

3 10
4 3 4
6 5 5

输出 #2

7


有机会,补一下滚动数组的各类题型

  • f [ i ] [ j ] [ k ] {f[i][j][k]} f[i][j][k]

    • i {i} i 表示当前状态或前一轮状态
    • j {j} j 表示当前背包体积
    • k {k} k 表示 % 7 {\%7} %7 的余数
  • 转移方程(01背包):

    • 不选 i {i} i f [ n o w ] [ j ] [ k ] = f [ p r e ] [ j ] [ k ] {f[now][j][k] = f[pre][j][k]} f[now][j][k]=f[pre][j][k]
    • i {i} i m a x ( f [ n o w ] [ j ] [ k ] , f [ p r e ] [ j − v [ i ] ] [ ( k + 7 − ( w [ i ] % 7 ) ) % 7 ] ) {max(f[now][j][k], f[pre][j-v[i]][(k + 7 - (w[i] \%7)) \%7] )} max(f[now][j][k],f[pre][jv[i]][(k+7(w[i]%7))%7])
#include<bits/stdc++.h>
// #include <bits/extc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>

#define fi first
#define sz size()
#define se second
#define endl ('\n')
#define pb push_back
#define ll long long
#define int long long
#define vi vector<int>
#define eb emplace_back
#define lowbit(x) (x & -x)
#define PII pair<int, int>
#define pqu priority_queue<int>
#define vii vector<vector<int>>
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define pql priority_queue<int,vi,greater<int>>
#define rep(i,a,n) for(ll i = (a); i < (n); ++i) 
#define Rep(i,a,n) for(ll i = (a); i <= (n); ++i) 
#define lb(v,x) (lower_bound(all(v),x)-(v).begin())
#define ub(v,x) (upper_bound(all(v),x)-(v).begin())
#define Dbug(x) (cout << #x << " <=> " << x << endl)
#define IOS cin.tie(0), cout.tie(0), ios_base::sync_with_stdio(false);

#define print(x,s,e) { Rep(i,s,e) cout << x[i] << ' '; cout << endl; }

const int N = 250010;
const int mod = 1000000007;

using namespace std;
using namespace __gnu_pbds;

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds; 
/*---------------------------------------------------------------------------------------------------------------------------*/
ll gcd(ll a, ll b){ if(b == 0){return a;} return gcd(b, a%b);}
ll lcm(ll a, ll b){ return (a * (b / gcd(a, b)));}
ll qmi(ll a, ll b){ if(!b) return 1ll; if(b&1) return a*qmi(a*a%mod, b>>1)%mod; return qmi(a*a%mod, b>>1)%mod;}
/*---------------------------------------------------------------------------------------------------------------------------*/

int n, m;
int w[N], v[N];
int f[2][1010][7];

void solve() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> w[i];
	for (int i = 1; i <= n; i++) cin >> v[i];
	
	memset(f, -1, sizeof f);
	f[0][0][0] = f[1][0][0] = 0;
	
	int pre = 0, now = pre ^ 1;
	
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= m; j++) {
			for (int k = 0; k < 7; k++) {
				f[now][j][k] = f[pre][j][k];
				if(j >= v[i] && f[pre][j - v[i]][(k - (w[i] % 7) + 7) % 7] != -1)
					f[now][j][k] = max(f[now][j][k], f[pre][j - v[i]][(k - (w[i] % 7) + 7) % 7] + w[i]);
			}
		}
		now ^= 1, pre ^= 1;
		// for (int j = 0; j <= m; j++)
			// for (int k = 0; k < 7; k++)
				// f[0][j][k] = f[1][j][k];
	}
	int res = 0;
	for (int i = 0; i <= m; i++) res = max(res, max(f[0][i][0], f[1][i][0]));
	cout << res << endl;
	return ;
}

signed main() {
	IOS int _ = 1;
	// cin >> _;
	while(_--) { solve(); }
	return 0;
}

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ღCauchyོꦿ࿐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值