【昆明之前每天补一道区域赛银/铜牌题】2021上海 I-Steadily Growing Steam(01背包变形)

题意:给出n个物品的体积和价值,可以选择最多k个的物品体积翻倍,问能否分出俩个子集,使这俩个子集的体积和相同且价值和最大

考虑从01背包入手,01背包的状态转移方程f[i][j]表示前i个物品放入容量为j的背包里的最大价值,那么f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]

考虑此题怎么从01背包转换过来,先不考虑子集这个概念,只考虑翻倍,那么我们可以多开一维,f[i][j][k]表示前i个物品,翻了j个,放入容量为k的背包里的最大价值,那么f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k-w[i]],f[i-1][j-1][k-2*w[i]]

再考虑分割体积和相同这个概念,我们可以把一个物品的体积看成有正负,正的代表放入集合S,负的代表放入集合T,为了方便划分(负数下标不好处理),我们就把边界成13*100=1300,那么最终答案就是max(f[n][0~t][1300]),转移方程就稍微变化了一点,因为有正有负,所以转移方程为

f[i][j][k]=max(f[i][j][k],f[i-1][j][k],f[i-1][j-1][k-w[i]]+v[i],f[i-1][j-1][k-2w[i]]+v[i],f[i-1][j-1][k+w[i]]+v[i],f[i-1][j-1][k+2w[i]]+v[i])

可以类似01背包一样开滚动数组优化掉一维,但是这题似乎不用?因为范围很小,直接暴力跑就行了。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define rep(i, a, b) for(int i=a;i<=b;i++)
#define per(i, a, b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=1e5+5;
const int M=1300;
const ll mod=1e9+7;
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}

int w[105],v[105];
int f[105][105][2601];

signed main()
{
    int n=read(),t=read();
    memset(f,-INF,sizeof f);
    f[0][0][M]=0;
    rep(i,1,n)
        v[i]=read(),w[i]=read();
    //dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k],dp[i-1][j-1][k-w[i]]+v[i],dp[i-1][j-1][k-2*w[i]]+v[i],dp[i-1][j-1][k+w[i]]+v[i],dp[i-1][j-1][k+2*w[i]]+v[i])
    rep(i,1,n)
       rep(j,0,t)
            rep(k,0,2ll*M)
            {
                f[i][j][k]=f[i-1][j][k];
                if(k>=w[i]) f[i][j][k]=max(f[i][j][k],f[i-1][j][k-w[i]]+v[i]);
                if(k>=2*w[i]&&j) f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k-2ll*w[i]]+v[i]);
                if(k+w[i]<=M) f[i][j][k]=max(f[i][j][k],f[i-1][j][k+w[i]]+v[i]);
                if(k+2*w[i]<=2*M&&j) f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k+2ll*w[i]]+v[i]);
            }
    ll ans=-INF;
    rep(i,0,t)
        ans=max(ans,f[n][i][M]);
    printf("%lld\n",ans);
}

全部评论

相关推荐

10-29 18:20
济南大学 Java
用微笑面对困难:他不是人事吗,怎么净特么不干人事
点赞 评论 收藏
分享
想干测开的tomca...:让我来压力你!!!: 这份简历看着“技术词堆得满”,实则是“虚胖没干货”,槽点一抓一大把: 1. **项目描述是“技术名词报菜名”,没半分自己的实际价值** 不管是IntelliDoc还是人人探店,全是堆Redis、Elasticsearch、RAG这些时髦词,但你到底干了啥?“基于Redis Bitmap管理分片”是你写了核心逻辑还是只调用了API?“QPS提升至1500”是你独立压测优化的,还是团队成果你蹭着写?全程没“我负责XX模块”“解决了XX具体问题”,纯把技术文档里的术语扒下来凑字数,看着像“知道名词但没实际动手”的实习生抄的。 2. **短项目塞满超纲技术点,可信度直接***** IntelliDoc就干了5个月,又是RAG又是大模型流式响应又是RBAC权限,这堆活儿正经团队分工干都得小半年,你一个后端开发5个月能吃透这么多?明显是把能想到的技术全往里面塞,生怕别人知道你实际只做了个文件上传——这种“技术堆砌式造假”,面试官一眼就能看出水分。 3. **技能栏是“模糊词混子集合”,没半点硬核度** “熟悉HashMap底层”“了解JVM内存模型”——“熟悉”是能手写扩容逻辑?“了解”是能排查GC问题?全是模棱两可的词,既没对应项目里的实践,也没体现深度,等于白写;项目里用了Elasticsearch的KNN检索,技能栏里提都没提具体掌握程度,明显是“用过但不懂”的硬凑。 4. **教育背景和自我评价全是“无效信息垃圾”** GPA前10%这么好的牌,只列“Java程序设计”这种基础课,分布式、微服务这些后端核心课提都不提,白瞎了专业优势;自我评价那堆“积极认真、细心负责”,是从招聘网站抄的模板吧?没有任何和项目挂钩的具体事例,比如“解决过XX bug”“优化过XX性能”,纯废话,看完等于没看。 总结:这简历是“技术名词缝合怪+自我感动式凑数”,看着像“背了后端技术栈名词的应届生”,实则没干货、没重点、没可信度——面试官扫30秒就会丢一边,因为连“你能干嘛”都没说清楚。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务