比赛: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
}
posted @ 2021-08-18 21:59  ssl_lhj  阅读(30)  评论(0)    收藏  举报