首页 > 其他分享 >AT_tdpc_knapsack ナップザック

AT_tdpc_knapsack ナップザック

时间:2024-11-25 22:15:47浏览次数:7  
标签:背包 int lim tdpc knapsack auto 物品 otimes

定义:\(A_c\) 表示颜色为 \(c\) 的物品集合,\(g \otimes S\) 表示背包 \(g\) 中插入集合 \(S\) 中的所有物品后的新背包。

刚开始想的是对于每种颜色,求出各自背包,然后进行 \(lim_c\) 次 \(O({lim_w}^2)\) 的合并。

显然 T 了,考虑漏了什么:本来操作 \(g \otimes S\) 是 \(O(|g| \cdot |s|)\) 的,当物品个数小于背包大小时,这种合并方式更加合理。

那么就好办了,设 \(f_{c,k}\) 表示考虑前 \(c\) 种颜色,使用 \(k\) 种颜色时的背包(下文中,前一维滚动掉,但是这样 \(k\) 需要倒序枚举)。

枚举使用 \(c\) 颜色去更新整个 \(f\),则 \(f_k \otimes A_c \to f_{k+1}\)。

因为物品总数为 \(n\),所以这么做是 \(O(nm\cdot lim_c)\) 的。

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
auto debug(auto ...b){((cerr << b << ' ') , ...); cerr << '\n';}
#else
#define debug(...) 0717
#endif

using ll = long long;
using uint = unsigned;

const int INF = 0x3F3F3F3F;
const ll INFl = 0x3F3F3F3F3F3F3F3F;

#define all(x) x.begin(),x.end()
#define r_all(x) x.rbegin(),x.rend()

const int N = 105;
const int S = 10005;
const int C = 53;

using gd = array<int , 2>;

int n , lim_w , lim_c;

vector<gd> a[C];

int f[C][S] , g[S];

signed main() {
#ifdef LOCAL
#elif defined(ONLINE_JUDGE)
#else
#endif
	
	ios::sync_with_stdio(0); cin.tie(0);
	
	cin >> n >> lim_w >> lim_c;
	for(int i = 1; i <= n; ++ i){
		int w , v , c;
		cin >> w >> v >> c;
		a[c].push_back({w , v});
	}
	
	for(int c = 1; c <= 50; ++ c){
		for(int k = lim_c - 1; k >= 0; -- k){
			copy(f[k] , f[k] + lim_w + 1 , g);
			for(auto [w , v] : a[c]) for(int j = lim_w; j >= 0; -- j){
				if(j + w <= lim_w) g[j + w] = max(g[j + w] , g[j] + v);
			}
			for(int j = 0; j <= lim_w; ++ j){
				f[k + 1][j] = max(f[k + 1][j] , g[j]);
			}
		}
	}
	
	int ans = 0;
	for(int k = 1; k <= lim_c; ++ k){
		ans = max(ans , *max_element(f[k] , f[k] + lim_w + 1));
	}
	cout << ans << '\n';
	
	return 0;
}

标签:背包,int,lim,tdpc,knapsack,auto,物品,otimes
From: https://www.cnblogs.com/TongKa/p/18568889

相关文章

  • [ABC373F] Knapsack with Diminishing Values
    AtCoder比较遗憾,E题用了太多时间了,没做出来。当时看到有平方感觉难道是斜率优化之类的?这下猜对了。拜谢WA90。不过官解好像没用斜率优化?不会。设\(f_{i,j}\)表示前\(i\)个物品一共用了\(j\)的体积。直接暴力做是三次方的。当加入一个体积为\(w\),价值为\(v\)的物品......
  • AT_tdpc_number 数 解题报告
    题目大意求\([1,N]\)中有多少个数在十进制表示下数码和是\(D\)的倍数。数据范围:\(1\leN\le10^{10000},1\leD\le100\)。思路很明显的数位dp。这里采用了记忆化搜索来实现数位dp。记忆化搜索实现比较板子,不光写起来比较简单,而且容易扩展,所以建议大家都学习一下。......
  • [AtCoder - tdpc_game] :ゲーム 题解
    [AtCoder-tdpc_game]:ゲーム题解一道小清新\(dp\)题。定义\(dp_{i,j}\)为第一堆山还有\(i\)个物品,第二堆山还有\(j\)个物品,すぬけ君能取得物品的最大价值。由于只能取两座山最上面的物品,假设当前两座山分别有\({x,y}\)个物品,すぬけ君选后只能有两种情况,分别为\(d......
  • AT_tdpc_number 数 题解
    题目传送门前置知识数位DP|记忆化搜索解法本题的提交在luogu上挂了,建议去原站或Vjudge上提交。基础数位DP,记录当前位置、已填的数码之和,接着记忆化搜索即可。需要注意的是\(0\bmodd=0\),如果写得不太好看(未处理前导零)的话需要减去其贡献。代码#include<bits/......
  • AT_abc169_f Knapsack for All Subsets题解
    如果我们定义\(dp[i][j]\)表示对于前i个字符而言,其子集满足条件的个数。那4么对于一个位置i而言,要么选择它贡献要么不选择,所以\(dp[i][j]=dp[i-1][j-a[i]](j>=a[i])+dp[i-1][j]\),这是每一个\(f(i)\)的函数。然后我们加上所有的\(dp[i][k](i:1到n)ans+=dp[i][k......
  • Knapsack 2
    这个题目的体积很大,但是价值却很小,最多是1e5,我们可以转变背包体积概念,把价值当作体积,然后体积当作DP值。dp[i]表示的是达到i价值所需的最小的体积#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=1e5+10;constintM=105;intdp[N];//......
  • Solving 0/1 knapsack problem with dynamic programming (英语课汇报)
    Solving0/1knapsackproblemwithdynamicprogrammingIntroduction0/1knapsackproblemsAlongtimeago,anexplorerwenttoanislandwherethereweretreasures,buthisknapsackcouldonlyholdamaximumweightof\(W\).Eachtreasurehaditscorresp......
  • AT_tdpc_tree 木
    题目描述:给定一棵大小为\(n\)的树,用另外\(n\)个点加边构造出这棵树,要求构造时所被边连到的点联通,求有多少连边顺序。数据范围:\(1\leqn\leq1000\)。思路:首先我们发现,因为题目要求连边后一定是一个连通块,所以考虑以哪一个点作为起点,然后向下连边。所以我们得到一个初......
  • AT_tdpc_tree 木 题解
    木弱智DP题,直接设\(f_i\)表示\(i\)子树内染色的方案数,然后每次合并一个点与它的儿子即可(具体而言,因为儿子间独立,所以方案数就是二项式系数)。需要注意的是因为第一条边可以在任意位置,所以要以每个点为根各DP一次。但是这样每条边会被算两次,所以乘以2的逆元即可。时间......
  • Gym101064L The Knapsack problem
    CF传送门发现物品的体积很小,尝试从此处入手。设\(K\)为最大的物品体积。把背包体积\(m\)分成差不超过\(K\)的两部分,然后合并。这样需要求出\(f(\frac{m}{2}-K\sim\frac{m}{2}+K)\)。递归地,可以发现需要求出\(f(\frac{m}{2^k}-K\sim\frac{m}{2^k}+K)\)。最......