多重背包(二进制优化) ------------------小吐槽:我还以为很难学呢,just so so~ https://www.luogu.com.cn/problem/P1833
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int h1,h2,m1,m2;
int n,w,ti[maxn],c[maxn],f[maxn],cnt;
int main()
{
scanf("%d:%d",&h1,&m1);scanf("%d:%d",&h2,&m2);
w=(h2-h1)*60-m1+m2;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(!z)
{
z=999999;
}
int t=1;
while(z>=t)
{
ti[++cnt]=x*t;
c[cnt]=y*t;
z-=t;
t<<=1;
}
if(z)
{
ti[++cnt]=x*z;
c[cnt]=y*z;
}
}
for(int i=1;i<=cnt;i++)
{
for(int j=w;j>=ti[i];j--)
f[j]=max(f[j],f[j-ti[i]]+c[i]);
}
cout<<f[w]<<endl;
return 0;
}
https://www.luogu.com.cn/problem/P1776
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,w,v[maxn],c[maxn],f[maxn];
int main()
{
int cnt=1;
scanf("%d%d",&n,&w);
for(int i=1;i<=n;i++)
{
int x,y,z;scanf("%d%d%d",&x,&y,&z);
int t=1;
while(z>=t)
{
v[cnt]=x*t;
c[cnt++]=y*t;
z-=t;
t<<=1;
}
if(z)
{
v[cnt]=x*z;
c[cnt++]=y*z;
}
}
cnt--;
for(int i=1;i<=cnt;i++)
{
for(int j=w;j>=c[i];j--)
{
f[j]=max(f[j],f[j-c[i]]+v[i]);
}
}
cout<<f[w]<<endl;
return 0;
}
经典深搜题:有助于理解深搜 https://www.luogu.com.cn/problem/P2066
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=20;
int n,m,a[maxn][maxn],f[maxn],ans[maxn],cnt;
void dfs(int id,int sum,int rest)
{
if(rest<0) return;
if(id==n+1)
{
if(sum>cnt)
{
cnt=sum;
for(int i=1;i<=n;i++)
f[i]=ans[i];
}
return;
}
for(int i=0;i<=m;i++)
{
ans[id]=i;
dfs(id+1,sum+a[id][i],rest-i);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
dfs(1,0,m);
cout<<cnt<<endl;
for(int i=1;i<=n;i++)
cout<<i<<" "<<f[i]<<endl;
return 0;
}
https://www.luogu.com.cn/problem/P1509 二维费用背包: 附加要求:约到数量最多的女孩,还要花的钱最少的时间 开两个二维数组分别记录
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=105;
int n,m,r,rmp[maxn],rp[maxn],f1[maxn][maxn],f2[maxn][maxn];
int ti[maxn];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&rmp[i],&rp[i],&ti[i]);
}
scanf("%d%d",&m,&r);
for(int i=1;i<=n;i++)
{
for(int v=m;v>=rmp[i];v--)
{
for(int u=r;u>=rp[i];u--)
{
int n1=f1[v][u];
int n2=f1[v-rmp[i]][u-rp[i]]+1;
int t1=f2[v-rmp[i]][u-rp[i]]+ti[i];
f1[v][u]=max(n1,n2);
if(n1==n2)
f2[v][u]=min(f2[v][u],t1);
else if(n2>n1)
f2[v][u]=t1;
}
}
}
int ans=inf;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=r;j++)
if(f1[m][r]==f1[i][j])
ans=min(ans,f2[i][j]);
}
cout<<ans<<endl;
return 0;
}
https://www.luogu.com.cn/problem/P1853 完全背包: 注意不断更新s的值
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e8+5;
int s,n,d,a[50],b[50],f[maxn];
int main()
{
scanf("%d%d%d",&s,&n,&d);
for(int i=1;i<=d;i++)
scanf("%d%d",&a[i],&b[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=d;j++)
{
for(int k=a[j];k<=s;k++)
f[k]=max(f[k],f[k-a[j]]+b[j]);
}
s+=f[s];
}
cout<<s<<endl;
return 0;
}
https://www.luogu.com.cn/problem/P2370 01背包+快排(根据题意) 注:虽然01背包队物品排列并不关心,但根据排序是非常必要的
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1005;
int n,p,s,dp[maxn],ans=inf,tmp;
struct node
{
int a,b;
}e[maxn];
bool cmp(node e1,node e2)
{
return e1.a<e2.a;
}
int main()
{
scanf("%d%d%d",&n,&p,&s);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&e[i].a,&e[i].b);
}
sort(e+1,e+n+1,cmp);
for(int i=1;i<=n;i++)
{
for(int j=s;j>=e[i].a;j--)
{
dp[j]=max(dp[j],dp[j-e[i].a]+e[i].b);
if(dp[j]>=p)
{
cout<<e[i].a<<endl;
return 0;
}
}
}
cout<<"No Solution!"<<endl;
return 0;
}
https://www.luogu.com.cn/problem/P2725 完全背包吧所有情况都罗列出来,如果需要的邮票数还是初始化的inf,则上一个数字就是答案
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e7+5;
int k,n,f[maxn],ans;
int main()
{
scanf("%d%d",&k,&n);
memset(f,inf,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
for(int j=x;j<=maxn;j++)
{
if(f[j-x]+1<=k)
f[j]=min(f[j],f[j-x]+1);
}
}
for(int i=1;i<=maxn;i++)
{
if(f[i]==inf)
{
ans=i-1;break;
}
}
cout<<ans<<endl;
return 0;
}
|