比赛:2021-08-12:B
题目大意
\(n\)个物品,每次去掉一个之后再询问的\(01\)背包问题。
题目分析
调整事情顺序,把第\(i\)个去掉的事情放在\(n-i+1\)个位置上,然后再做一次二维\(01\)背包,然后输出\(f_{m,n} \to f_{m,1}\)(\(f_{i,j}\)表示有\(i\)点精力,做前\(j\)件事情时能取得的最大值)
因为第\(1\)个被去掉的事情被放在了第\(n\)个位置上,所以\(f_{m,n-1}\)刚好就是去掉第\(1\)件事情后的结果。
最后再用快读快输再优化一下下(貌似不用也可以),就能\(AC\)啦。
\(Code\)
#include<iostream>
#include<cstdio>
#define Luan_Gao_YYDS return 0;
#define sco 10010
#define getcha() (S==T&&(T=(S=fsr)+fread(fsr,1,1<<15,stdin),S==T)?EOF:*S++)
using namespace std;
int a[sco],b[sco],f[sco][4010],w[sco],c[sco],n,m,tot(0);
char fsr[1<<15],*S=fsr,*T=fsr;
inline int read(){
int r(0),w(1);char ch;
while(ch=getcha(),ch>=58 || ch<=47)w=(ch=='-'?-1:1);r=(r<<3)+(r<<1)+ch-48;
while(ch=getcha(),ch<=57 && ch>=48)r=(r<<3)+(r<<1)+ch-48;
return r*w;
}
inline void wri(int x){
if(x>=10)wri(x/10);
putchar(x%10+48);
}
inline void wris(int x){
wri(x);putchar(10);
}
int main(){
n=read();m=read();
for(int i=1;i<=n;++i){
a[i]=read();b[i]=read();
tot+=i;
}
for(int i=1;i<n;++i){
int x;
x=read();
tot-=x;
w[n-i+1]=a[x];c[n-i+1]=b[x];
}
w[1]=a[tot];c[1]=b[tot];
for(int i=1;i<=m;++i){
for(int j=1;j<=n;++j){
if(w[j]<=i) f[i][j]=max(f[i][j-1],f[i-w[j]][j-1]+c[j]);
else f[i][j]=f[i][j-1];
}
}
for(int j=n;j>0;--j){
wris(f[m][j]);
}
Luan_Gao_YYDS
}

浙公网安备 33010602011771号