CF922E Birds 题解
前置知识
解法
观察到 \(w\) 极大,若使用正常的背包空间会爆炸。
依据 AT_dp_e Knapsack 2 的经验,考虑将背包“反”着用。设 \(f_{i,j}\) 表示到第 \(i\) 棵树时一共召唤了 \(j\) 只小鸟时剩余的最大魔力值,状态转移方程为 \(f_{i,j}=\min(\max\limits_{k=0}^{\min(j,c_{i})} \{ f_{i-1,j-k}-cost_{i} \times k+x \},w+b \times j)\),边界为 \(f_{0,0}=w\)。
最终,有 \(\max\limits_{i=0}^{\sum_{j=1}^{n}c_{j}} \{ [f_{n,i} \ge 0] \times i \}\) 即为所求。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
ll c[10010],sum[10010],cost[10010],f[1010][10010];
int main()
{
ll n,w,b,x,ans=0,i,j,k;
cin>>n>>w>>b>>x;
for(i=1;i<=n;i++)
{
cin>>c[i];
sum[i]=sum[i-1]+c[i];
}
for(i=1;i<=n;i++)
{
cin>>cost[i];
}
memset(f,-0x3f,sizeof(f));
f[0][0]=w;
for(i=1;i<=n;i++)
{
for(j=0;j<=sum[i];j++)
{
for(k=0;k<=min(j,c[i]);k++)
{
if(f[i-1][j-k]-cost[i]*k>=0)
{
f[i][j]=max(f[i][j],f[i-1][j-k]-cost[i]*k+x);
}
}
f[i][j]=min(f[i][j],w+b*j);
}
}
for(i=sum[n];i>=0;i--)
{
if(f[n][i]>=0)
{
ans=i;
break;
}
}
cout<<ans<<endl;
return 0;
}
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18091823,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。