搬运工
这道题正解明明是 \(\rm DP\) 啊,为什么题解区几乎都是暴力啊。。。
题目大意
有三堆书,分别有 \(n,m,k\) 本。给定 \(n,m,k\) 和每本书的重量 \(a,b,c\)。
每次取书只能取每堆最上面的,每次取书的代价为 \(val\times weight\)。
其中 \(val\) 表示这是第 \(val\) 次取书,\(weight\) 表示这本书的重量。
题目分析
显然看到数据范围 \(1\le n,m,k\le100\) ,于是可以推测时间复杂度是 \(O(n\times m\times k)\)。
令 \(dp[i][j][v]\) 表示三个书堆恰好取了 \(i,j,v\) 本时的最大价值,\(tot=n+m+k\),\(val=tot-i-j-v+1\)。
\(tot\) 是书的总量,\(val\) 是当前的取书次数。
当 \(i\neq 0\) 时,有:
\[dp[i][j][v]=\max\{dp[i][j][v],val\times a[i]+dp[i-1][j][v]\}
\]
当 \(j\neq 0\) 时,有:
\[dp[i][j][v]=\max\{dp[i][j][v],val\times b[j]+dp[i][j-1][v]\}
\]
当 \(v\neq 0\) 时,有:
\[dp[i][j][v]=\max\{dp[i][j][v],val\times c[v]+dp[i][j][v-1]\}
\]
代码
const int ma=105;
int a[ma],b[ma],c[ma];
int dp[ma][ma][ma];
int n,m,k;
int main(void)
{
n=read(),m=read(),k=read();
int tot=n+m+k;
for(register int i=1;i<=n;i++)
{
a[i]=read();
}
for(register int i=1;i<=m;i++)
{
b[i]=read();
}
for(register int i=1;i<=k;i++)
{
c[i]=read();
}
for(register int i=0;i<=n;i++)
{
for(register int j=0;j<=m;j++)
{
for(register int v=0;v<=k;v++)
{
int val=tot-i-j-v+1;
if(i!=0)
{
dp[i][j][v]=max(dp[i][j][v],a[i]*val+dp[i-1][j][v]);
}
if(j!=0)
{
dp[i][j][v]=max(dp[i][j][v],b[j]*val+dp[i][j-1][v]);
}
if(v!=0)
{
dp[i][j][v]=max(dp[i][j][v],c[v]*val+dp[i][j][v-1]);
}
}
}
}
printf("%d\n",dp[n][m][k]);
return 0;
}

浙公网安备 33010602011771号