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);
}

浙公网安备 33010602011771号