版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/88957931
观察发现,我们加血和攻击是两个互不影响的操作,只要保证我们时刻存活就可以进行攻击,而攻击又有一些约束条件,方便起见,我们设置三个子任务
- 处理出,保证自己存活的情况下,可以有多少天自由行动(不回血)
- 在完成 后处理出,自由行动的时候,花多少天能够对大佬造成多少伤害,要具体到每一个可能数值上,因为只能把血打成0,这里只考虑攻击一次
- 在完成 后,我们能否击败每个大佬
对于
,一个简单dp即可
对于
,搜索一下,map或者hash判重
对于
,我们分析一下限制条件,写成不等式得到:
把二式移项,令D单独在左边,枚举
,则如果
为有序,那么根据一式便满足单调性,要求
的最小值就很好求了
特殊情况:如果可以直接嘴炮打死,就直接输出1
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=105,INF=990000000;
struct fxxk{int day,F,L;};
map<int,int>mp[N];
pair<int,int>s[2000005];
int n,m,f[N][N],w[N],a[N],mc,D=0,c[N],lim,cnt=0;
inline void dp(){
memset(f,128,sizeof(f));f[0][mc]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=mc-a[i];j++){
f[i][min(mc,j+w[i])]=max(f[i][min(mc,j+w[i])],f[i-1][j+a[i]]);
f[i][j]=max(f[i][j],f[i-1][j+a[i]]+1);
D=max(D,f[i][j]);
}
}
inline void bfs(int tot){
queue<fxxk>q;q.push((fxxk){1,1,0});
while(!q.empty()){
fxxk x=q.front();q.pop();
if(x.day<tot){
q.push((fxxk){x.day+1,x.F,x.L+1});
if(x.L>1 && x.F<lim/x.L && !mp[x.L][x.L*x.F]){
fxxk y=(fxxk){x.day+1,x.F*x.L,x.L};
mp[x.L][x.L*x.F]=1;
s[++cnt]=make_pair(y.F,y.day);q.push(y);
}
}
}
}
int main(){
n=read();m=read();mc=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) w[i]=read();
for(int i=1;i<=m;i++) c[i]=read(),lim=max(lim,c[i]);
dp();
bfs(D);sort(s+1,s+cnt+1);
for(int i=1;i<=m;i++){
int ans=0,minn=INF;
if(c[i]<D){puts("1");continue;}
for(int j=cnt,k=1;j;j--){
while(k<=cnt && s[k].first+s[j].first<=c[i]) minn=min(minn,s[k].second-s[k].first),k++;
if(minn+c[i]-s[j].first+s[j].second<=D){ans=1;break;}
if(s[j].first<=c[i] && s[j].second+c[i]-s[j].first<=D) {ans=1;break;}
}
cout<<ans<<"\n";
}
return 0;
}