CF1398D 彩色长方形
1 CF1398D 彩色长方形
2 题目描述
给你多组三种颜色的彩色小棒:
\(𝑅\) 对红色棒,第一对长度为 \(𝑟_1\),第二对长度为 \(𝑟_2\),...,第 \(𝑅\) 对长度为 \(𝑟_𝑅\);
\(𝐺\) 对绿色棒,第一对长度为 \(𝑔_1\),第二对长度为 \(𝑔_2\),...,第 \(𝐺\) 对长度为 \(𝑔_𝐺\);
\(𝐵\) 对蓝色棒,第一对长度为 \(𝑏_1\),第二对长度为 \(𝑏_2\),...,第 \(𝐵\) 对长度为 \(𝑏_𝐵\);
用以下过程这些对彩色小棒拼接长方形:
- 拿一对某一种颜色的小棒;
- 拿一对与第一对不同颜色的小棒;
- 将生成矩形的面积增加到总面积中。
这样拼接得到的长方形,它们的相对边为相同的颜色,它们的相邻边是不同的颜色。
每对木棒最多可以使用一次,不需要用完所有的小棒。每一对棒子都不能拆开。
你能达到的最大面积是多少?
3 题解
这道题看上去贪心可行,但是存在一种特殊情况:当每次在三种颜色中取最优的两种时,有可能存在两种颜色已经全部取完,而剩下比较多的另外一种颜色的情况。例如:
3 1 1
19 19 19
20
20
这种情况下,暴力计算的值为 \(400\),而将 \(r\) 颜色中的 \(19\) 分别与 \(g\) 和 \(b\) 的 \(20\) 匹配,得到答案为 \(760\),大于 \(400\)。
我们发现:这种情况下贪心不成立是因为选取方案问题,所以我们仍然从大到小考虑答案。然后我们考虑 \(dp\):根据题目,可以得出三维状态:\(dp_{i, j, k}\) 表示 \(r\) 中选择前 \(i\) 个,\(g\) 中选择前 \(j\) 个,\(b\) 中选择前 \(k\) 个时能得到的最大价值。\(dp\) 方程也随之明了:
\[dp_{i, j, k} = max(dp_{i-1, j-1, k} + r_i * g_j, dp_{i-1, j, k-1} + r_i * b_k, dp_{i, j-1, k-1} + g_j * b_k)
\]
注意:选取完可能会有剩余,所以目标状态不是 \(dp_{R, G, B}\),而是所有状态中的最大值。
4 代码(空格警告):
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 205;
int R, G, B, ans;
int r[N], g[N], b[N];
int dp[N][N][N];
bool cmp(int x, int y) {return x > y;}
int Max(int x, int y)
{
if (x > y) return x;
else return y;
}
int main()
{
cin >> R >> G >> B;
for (int i = 1; i <= R; i++) cin >> r[i];
for (int i = 1; i <= G; i++) cin >> g[i];
for (int i = 1; i <= B; i++) cin >> b[i];
sort(r+1, r+R+1, cmp);
sort(g+1, g+G+1, cmp);
sort(b+1, b+B+1, cmp);
for (int i = 0; i <= R; i++)
{
for (int j = 0; j <= G; j++)
{
for (int k = 0; k <= B; k++)
{
if (i != 0 && j != 0) dp[i][j][k] = dp[i-1][j-1][k] + r[i] * g[j];
if (j != 0 && k != 0) dp[i][j][k] = Max(dp[i][j][k], dp[i][j-1][k-1] + g[j] * b[k]);
if (i != 0 && k != 0) dp[i][j][k] = Max(dp[i][j][k], dp[i-1][j][k-1] + r[i] * b[k]);
ans = Max(ans, dp[i][j][k]);
}
}
}
cout << ans;
return 0;
}