Colored Rectangles

意义:有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
#include
#include

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);
}

你可能感兴趣的:(补题)