题目链接:点我啊╭(╯^╰)╮
题目大意:
中文题
解题思路:
发现自己的自信值是否足够和能否打败大佬是两码事
因此可以先用一个
D
P
DP
DP 求出最多可以腾出多少天可以来蓄力,设最多有
D
D
D 天
然后接下来肯定是用一个
D
P
DP
DP 求出最终答案,但是这个
D
P
DP
DP 用什么来最为转移的数据完全不知道
那么假设有一个
p
a
i
r
:
(
d
,
f
)
pair:(d, f)
pair:(d,f),表示用
d
d
d 天,可以造成
f
f
f 的攻击
也就是说如果知道了所有的
p
a
i
r
pair
pair,就可以进行
d
p
dp
dp 了(虽然还不知道怎么
d
p
dp
dp )
很明显,可以通过
B
F
S
BFS
BFS 来求出所有
p
a
i
r
pair
pair ,那么如何计算时间复杂度呢?
可以猜测必须通过这些
p
a
i
r
pair
pair 进行
d
p
dp
dp ,那么这些
p
a
i
r
pair
pair 的数量一定不会太大
所以可以直接
B
F
S
BFS
BFS 就完事了!注意要去重
如果最多只能攻击一次,则只需满足
f
≤
c
f ≤ c
f≤c
&
&
\&\&
&&
f
+
D
−
d
≥
c
f + D - d ≥ c
f+D−d≥c 即可
如果能攻击两次,设对应的两个
p
a
i
r
pair
pair 为
(
d
1
,
f
1
)
,
(
d
2
,
f
2
)
(d1, f1) ,(d2, f2)
(d1,f1),(d2,f2)
f
1
+
f
2
≤
c
f1 + f2 ≤ c
f1+f2≤c
&
&
\&\&
&&
f
1
+
f
2
+
(
D
−
d
1
−
d
2
)
≥
c
f1 + f2 + (D - d1 - d2) ≥ c
f1+f2+(D−d1−d2)≥c
暴力枚举肯定不行, 那么思考是否能满足决策优化
对
f
f
f 进行从小到大的排序,则随着
f
1
f1
f1 的增大,
f
2
f2
f2 一直减少
但如果这样枚举会产生不合法的
p
a
i
r
pair
pair,只需要对
f
1
f1
f1 从大到小枚举即可
特别注意要特判单独的
f
1
f1
f1 是否满足 以及
c
≤
D
c ≤ D
c≤D 的情况
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 105;
int n, m, mc, a[maxn], w[maxn], c[maxn];
int D, dp[maxn][maxn], mxc, top;
map <pii, int> mp;
struct node{
int d, f, l;
bool operator < (const node A) const {
if(f == A.f) return d < A.d;
return f < A.f;
}
} st[2000005];
int getD(){
for(int i=1; i<=n; i++)
for(int j=a[i]; j<=mc; j++){
dp[i][j-a[i]] = max(dp[i][j-a[i]], dp[i-1][j] + 1);
int nj = min(mc, j - a[i] + w[i]);
dp[i][nj] = max(dp[i][nj], dp[i-1][j]);
}
int ret = 0;
for(int i=1; i<=n; i++)
for(int j=0; j<=mc; j++)
ret = max(ret, dp[i][j]);
return ret;
}
void bfs(){
queue <node> q;
node u = {1, 1, 0}, v;
q.push(u);
while(q.size()){
u = q.front(), q.pop();
if(u.d >= D) continue;
q.push({u.d + 1, u.f, u.l + 1});
if(u.l <= 1 || 1ll * u.f * u.l > 1ll * mxc) continue;
if(mp[{u.d + 1, u.f * u.l}]) continue;
v.d = u.d + 1, v.f = u.f * u.l, v.l = u.l;
q.push(v), mp[{u.d + 1, u.f * u.l}] = 1;
st[++top] = {u.d + 1, u.f * u.l};
}
}
signed main() {
scanf("%d%d%d", &n, &m, &mc);
for(int i=1; i<=n; i++) scanf("%d", a+i);
for(int i=1; i<=n; i++) scanf("%d", w+i);
for(int i=1; i<=m; i++) scanf("%d", c+i), mxc = max(mxc, c[i]);
D = getD();
bfs();
sort(st+1, st+1+top);
for(int i=1; i<=m; i++){
int f = 0, mx = -1e9;
if(c[i] <= D) {
printf("%d\n", 1);
continue;
}
for(int f1=top, f2=1; f1; f1--){
while(f2 < top && st[f1].f + st[f2].f <= c[i])
mx = max(mx, st[f2].f - st[f2].d), f2++;
if(st[f1].f+D-st[f1].d+mx >= c[i]) {
f = 1;
break;
}
if(st[f1].f<=c[i] && st[f1].f-st[f1].d+D >= c[i]) {
f = 1;
break;
}
}
printf("%d\n", f);
}
}