欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

D. Colored Rectangles(动态规划问题) Educational Codeforces Round 93 (Rated for Div. 2)

程序员文章站 2022-03-12 09:53:48
...

原题链接: http://codeforces.com/contest/1398/problem/D

D. Colored Rectangles(动态规划问题) Educational Codeforces Round 93 (Rated for Div. 2)
样例:

input
1 1 1
3
5
4
output
20
input
2 1 3
9 5
1
2 8 5
output
99
input
10 1 1
11 7 20 15 19 14 2 4 13 14
8
11
output
372

题意: 你有三对彩棒的多重集合,即G,B,C三个数组,每个数组中元素代表的是对应彩棒的长度。你可以选择颜色不同的两对彩棒形成一个矩形。即形成的矩形它们的相对侧是相同的颜色,而相邻的侧是不同的颜色。问你能形成的总矩形面积之和最大值为多少?

解题思路: 由于很多信息我们都不明了,我们对于这个问题会比较模糊。但我们仔细想想我们求总矩形面积之和的最大值问题(即最优解)是不是可以转换为更小的子问题?设我们可以构造的最大矩形数为nn,(注意:最大矩形数是一定固定的)那么该状态的最优解是不是可以转换为矩形数为n1n-1的最优解+当前可构建矩形面积的最大值。我们用dp[i][j][k]dp[i][j][k]表示用去了ii个R颜色彩棒,jj个G个颜色彩棒,kk个C颜色彩棒,那么我们表示矩形数为n1n-1自然对应的彩棒数要减2了,这里注意有三种情况都要判断。有了这个思路,我们是不是可以利用动态规划的思想自底向上(当然也可以自顶向下,利用递归,但占空间量肯定很大。),OK,我们的状态转移方程,具体看代码即可。

AC代码:

/*
*邮箱:aaa@qq.com
*blog:https://me.csdn.net/hzf0701
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*
*/
#include<bits/stdc++.h>	//POJ不支持

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 200+2;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//

int r,g,c;
int R[maxn],G[maxn],C[maxn];
int dp[maxn][maxn][maxn];
int main(){
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	IOS;
	while(cin>>r>>g>>c){
		memset(dp,0,sizeof(dp));
		rep(i,0,r-1)cin>>R[i];
		rep(i,0,g-1)cin>>G[i];
		rep(i,0,c-1)cin>>C[i];
		sort(R,R+r);sort(G,G+g);sort(C,C+c);
		//排序。
		rep(i,0,r){
			rep(j,0,g){
				rep(k,0,c){
					if(i>0&&j>0){
						dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+R[i-1]*G[j-1]); //状态转移
					}
					if(i>0&&k>0){
						dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-1]+R[i-1]*C[k-1]); //状态转移
					}
					if(j>0&&k>0){
						dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k-1]+G[j-1]*C[k-1]); //状态转移
					}
				}
			}
		}
		cout<<dp[r][g][c]<<endl;
	}
	return 0;
}