【问题描述】
陈老师喜欢网购书籍,经常一次购它个百八十本,然后拿来倒卖牟取暴利。前些天,高一的新同学来了,他便像往常一样兜售他的书,经过一番口舌,同学们决定买他的书,但是陈老师桌上的书有三堆,每一堆都有厚厚的一叠,他要想个办法用最轻松的方式把书拿下来给同学们。但是你想逗一下陈老师,于是你设计一个最累的方式给他。若告诉你这三堆分别有i,j,k本书,以及每堆从下到上书的质量,每次取书只能从任一堆的最上面取,那么请你设计一个方案,让他花最大的力气取下所有的书。
显然,每次取书陈老师的体力消耗都会加大,这里用体力系数代表,取下第一本书时,体力系数为1,第二本书时体力系数为2,依次类推,而每次体力消耗值则为体力系数与书的重量之积。
【输入】
第一行3个整数,分别为三堆书的数量i,j,k 第二行至第四行分别为每堆由下至上的书本重量 【输出】
陈老师喜欢网购书籍,经常一次购它个百八十本,然后拿来倒卖牟取暴利。前些天,高一的新同学来了,他便像往常一样兜售他的书,经过一番口舌,同学们决定买他的书,但是陈老师桌上的书有三堆,每一堆都有厚厚的一叠,他要想个办法用最轻松的方式把书拿下来给同学们。但是你想逗一下陈老师,于是你设计一个最累的方式给他。若告诉你这三堆分别有i,j,k本书,以及每堆从下到上书的质量,每次取书只能从任一堆的最上面取,那么请你设计一个方案,让他花最大的力气取下所有的书。
显然,每次取书陈老师的体力消耗都会加大,这里用体力系数代表,取下第一本书时,体力系数为1,第二本书时体力系数为2,依次类推,而每次体力消耗值则为体力系数与书的重量之积。
举个例子:三堆书及重量如下:
9
2 10 3
第一堆 第二堆 第三堆
显然最累的取书方案是:右左左中,即:3*1+9*2+2*3+10*4=67。【输入】
第一行3个整数,分别为三堆书的数量i,j,k 第二行至第四行分别为每堆由下至上的书本重量 【输出】
输出最累方式的体力消耗总值。
【样例】
book.in
3 2 4
2 3 2
1 5
9 8 7 4
book.out
257
【数据规模】对于40%的数据有0≤i,j,k<10; 对于100%的数据有0≤i,j,k<100
【题解】
很容易想到是dp,因为假如说f[i][j][k]表示第一堆取了前i本,第二堆取了前j本,第三堆取了前k本的最大体力值,那么这种状态的表示对以后是没有影响的,也就是说满足了无后效性和最优子结构。
那么方程就很简单了,f[i][j][k]从前一个状态递推出来的话只有三种情况:上一步从第1堆取,上一步从第2堆取,上一步从第3堆取。
【代码】
#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 2100000000
using namespace std;
int I,J,K;
int a[105],b[105],c[105],f[105][105][105];
int main(){
freopen("book.in","r",stdin);
freopen("book.out","w",stdout);
scanf("%d%d%d",&I,&J,&K);
for (int i=I;i>=1;--i)
scanf("%d",&a[i]);
for (int i=J;i>=1;--i)
scanf("%d",&b[i]);
for (int i=K;i>=1;--i)
scanf("%d",&c[i]);
for (int i=0;i<=I;++i)
for (int j=0;j<=J;++j)
for (int k=0;k<=K;++k){
if (i-1>=0) f[i][j][k]=f[i-1][j][k]+a[i]*(i+j+k);
if (j-1>=0) f[i][j][k]=max(f[i][j][k],f[i][j-1][k]+b[j]*(i+j+k));
if (k-1>=0) f[i][j][k]=max(f[i][j][k],f[i][j][k-1]+c[k]*(i+j+k));
}
printf("%d\n",f[I][J][K]);
}