罗p 5858“swtr-03”金剑
标题链接:
https://www.luogu.com.cn/problem/P5858
主要观点:
小娥打算铸剑。现在有n种的原料,编号从1到N,下标I的原料的固体值是ai。它们以1比N的顺序加入炼丹炉中,但炼丹炉只能容纳w原料,每种原料加入前最多只能取出s种原料。剑的耐久性是所有原材料的耐久性之和,而第I种原材料的耐久性是锅内原材料的总数(包括正在放入的)* ai,寻求最大的耐久性。
思考:
原料摆放整齐,同时限制添加原料。可以想象构建一个二维的DP数组DP [I] [J],其中I表示当前放入了哪些原料,J表示当前炉内有多少原料,所以我们可以写下面的代码。
for(LL I=1;I=n;I) //目前原材料有哪些?
for(LL j=w;j=1;j-)//现在的炉子里有多少原料?
for(LL k=j-1;k=最小值(w,j s-1);K) //投入前可能留下的原材料
dp[i][j]=最大值(dp[i][j],DP[I-1][k]j * a[I]);//添加新原料
上述代码的时间复杂度为O(n * w * w),所以我们考虑优化。可以看出,最里面的for循环实际上是在找到最大的耐久性后添加新的原材料,这可以通过单调的队列来实现。
代码:
#包含位/stdc。h
使用命名空间标准;
#定义LL长长
const LL INF=-1e 16 10;
const int maxn=5e3 10
LL n,w,s,dp[maxn][maxn],ans,q[maxn],pos[maxn];
向量L1 a(maxn);
int main(){ 0
cin西北;
for(LL I=1;I=n;(一)
scanf('%lld ',a[I]);
for(LL I=0;I=n;(一)
for(LL j=0;j=w;j)
DP[I][j]=INF;
DP[0][0]=0;
for(LL I=1;I=n;I){ 0
LL l=1,r=1;
q[l]=DP[I-1][w];
pos[l]=w;
for(LL j=w;j=1;j-){ 0
而(l=r位置[l]j s-1)l;//取出原材料
而(l=r q[r]DP[I-1][j-1])r-;//构建单调递减的队列
位置[r]=j-1;//记录添加的原材料数量。
q[r]=DP[I-1][j-1];
DP[I][j]=q[l]j * a[I];
}
}
ans=INF
for(LL I=0;I=w;(一)
ans=max(ans,DP[n][I]);
cout ans ' \ n
返回0;
}
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/74745.html