ABC 364
- 给定 , 记 是第一个让 或 成立的位置, 你可以重排二元组,请求最大的 .
- 标签:二维背包,思维题,判重
- 暴力: 记 表示 ,最多能选几个数,有转移:
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
#define G(i,r,l) for(int i(r);i>=l;--i)
using namespace std;
using ll = long long;
int f[10005][10005];
int n,a[88],b[88],X,Y;
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n>>X>>Y;
F(i,1,n) cin>>a[i]>>b[i];
F(i,1,n) G(j,X,a[i]) G(k,Y,b[i]) f[j][k]=max(f[j-a[i]][k-b[i]]+1,f[j][k]);
cout<<min(f[X][Y]+1,n)<<"\n";
return 0;
}
- 优化:观察到 的值域很小只有 80, 而状态过大,我们考虑把其中一维和值域交换, 即采用交换权值法
- 记 表示最终选 个数, 时最小的 , 最后只需要判断什么时候 全部大于 即可. 有转移:
- 初始化所有 为 , 但 .
- 由于涉及到选几个数, 要做 次01背包, 所以即使倒着扫也无法保证不选重.
- 解决方法是开一个 . 表示当 最小时 有没有被用过,更新可以在 过程中完成,复杂度仍然是对的, 详见代码。
- 时间复杂度就变成 啦!
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
#define G(i,r,l) for(int i(r);i>=l;--i)
using namespace std;
using ll = long long;
const int inf=0x3f3f3f3f;
int f[83][10005],psy[100005],pos[100005];
bool vis[83][10005][83];
struct node{
int a,b;
bool operator <(const node &o)const{
return a==o.a?b<o.b:a<o.a;
}
}c[88];
int n,X,Y;
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n>>X>>Y;
F(i,1,n) cin>>c[i].a>>c[i].b;
sort(c+1,c+n+1);
memset(f,0x3f,sizeof(f));
f[0][0]=0;
F(i,1,n) {
memset(pos,0,sizeof(pos));
memset(psy,0,sizeof(psy));
G(j,X,1) {
F(k,1,n) {
if(j<c[k].a) break;
int tmp=f[i-1][j-c[k].a]+c[k].b;
if(!vis[i-1][j-c[k].a][k] && f[i][j]>tmp) {
psy[j]=j-c[k].a;
f[i][j]=tmp;
pos[j]=k;
}
}
}
F(j,1,X){
if(psy[j]) F(k,1,n) vis[i][j][k] = vis[i-1][psy[j]][k];
if(pos[j]) vis[i][j][pos[j]]=1;
}
}
int ans=n;
F(i,1,n){
bool tag=0;
F(j,1,X) if (f[i][j]<=Y) tag=1;
if(!tag) return cout<<i<<"\n",0;
}
cout<<n<<"\n";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】