UVA11450 题解

分组 0/1 背包模型。

由于没有翻译,我开始时理解错了题意,这里解释一下题意:

给定几个组,每个组中有一些物品,每个物品有价格。你需要在每个组中选择一个物品,求最后在花费不超过预算 \(m\) 的情况下,能花费的最大价格。

如果无法实现输出 no solution

考虑 \(dp_{i,j}=0/1\) 表示选择第 \(i\) 组时,恰好花费 \(j\) 圆能否实现,\(1\) 代表可以,\(0\) 代表不行。

遍历每组,遍历其中每个物品(假设此物品的价格为 \(w\)),枚举 \(j\) 。当且仅当上一组的状态中,恰好花费 \(j-w\) 能实现,当前状态才能实现,那么就让我们从 \(dp_{i-1,j-w}\) 转移过来。

可以 bitset,滚动数组优化,但数据范围小,不必。

#include<bits/stdc++.h>
#define endl '\n'
using ll=long long;
using ull=unsigned long long;
using ld=long double;
using namespace std;
int t;
const int N=30;
int w[N][N];
bool dp[N][210];
inline void solve(){
	cin>>t;
	while(t--)
	{
		int m,c;
		int k[N];
		cin>>m>>c;
		for(int i=1;i<=c;i++)
		{
			cin>>k[i];
			for(int j=1;j<=k[i];j++)
				cin>>w[i][j];
		}	
		memset(dp,0,sizeof dp);
		dp[0][0]=1;
		for(int i=1;i<=c;i++)
		for(int j=1;j<=k[i];j++)
		for(int p=w[i][j];p<=m;p++)
		dp[i][p]|=dp[i-1][p-w[i][j]];
		int ans=-1;
		for(int i=m;i>=0;i--)
		if(dp[c][i]){ans=i;break;}
		if(ans==-1)cout<<"no solution\n";
		else cout<<ans<<'\n';
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	solve();
	const int _=0;
	return ~~(0^_^0);
}
posted @ 2025-03-01 17:37  xcr0987  阅读(21)  评论(0)    收藏  举报