意义:有r对红色木棒,g对绿色木棒,b对蓝色木棒,用他们构成矩形,矩形的对边颜色相同,邻边颜色不同,问组成的矩形面积之和最大为多少(一对木棒只能用于一个矩形)
如果邻边的边长都最大,那么得到的矩形的面积也最大,最初我就是采用这种贪心的方案去写题,先排序然后找不同颜色最长的边,然后WA了,然后仔细一想发现这样是有问题的,简单的hack数据:r[]={5,5},g[]={6},r[]={6},按上述方案答案是36,但显然有更大的答案:60,所以这种思路在只有两种颜色时是可行的,但当颜色种类为三时在某些情况下是不满足的。
好了,上面都是我做的时候的错误示范,正确做法是dp,记dp[i][j][k]为红色木棒使用i对,绿色木棒使用j对,蓝色木棒使用k对时围成的矩形的总面积,我们的答案即是范围内所有的i,j,k的dp[i][j][k]的最大值。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 210;
typedef long long ll;
ll dp[N][N][N];
ll nr[N], ng[N], nb[N];
bool cmp(ll a, ll b) {
return a > b;
}
int main() {
int n, m, q;
ll ans = 0;
scanf("%d %d %d", &n, &m, &q);
for (int i = 1; i <= n; i++) scanf("%lld", &nr[i]);
for (int i = 1; i <= m; i++) scanf("%lld", &ng[i]);
for (int i = 1; i <= q; i++) scanf("%lld", &nb[i]);
sort(nr + 1, nr + 1 + n, cmp);
sort(ng + 1, ng + 1 + m, cmp);
sort(nb + 1, nb + 1 + q, cmp);
//dp循环有两种,当下标从1开始时需要下述处理某个为0的情况,当下标从0开始则不需要,为便于理解这里给出下标从1开始的代码
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - 1][0] + nr[i] * ng[j]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= q; j++) {
dp[i][0][j] = max(dp[i][0][j], dp[i - 1][0][j-1] + nr[i] * nb[j]);
}
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= q; j++) {
dp[0][i][j] = max(dp[0][i][j], dp[0][i - 1][j-1] + ng[i] * nb[j]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int k =1; k <= q; k++) {
dp[i][j][k] = max(dp[i][j][k], dp[i-1][j-1][k] + nr[i] * ng[j]);
dp[i][j][k] = max(dp[i][j][k], dp[i-1][j][k-1] + nr[i] * nb[k]);
dp[i][j][k] = max(dp[i][j][k], dp[i][j-1][k-1] + ng[j] * nb[k]);
ans = max(ans, dp[i][j][k]);
}
}
}
printf("%lld\n",ans);
}