搬运工

洛谷题面

这道题正解明明是 \(\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;
}
posted @ 2021-10-26 13:57  Coros_Trusds  阅读(70)  评论(0)    收藏  举报