搬运工

洛谷题面

这道题正解明明是 \(\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  阅读(52)  评论(0)    收藏  举报