D. Colored Rectangles(动态规划问题) Educational Codeforces Round 93 (Rated for Div. 2)
程序员文章站
2022-03-12 09:53:48
...
原题链接: http://codeforces.com/contest/1398/problem/D
样例:
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三个数组,每个数组中元素代表的是对应彩棒的长度。你可以选择颜色不同的两对彩棒形成一个矩形。即形成的矩形它们的相对侧是相同的颜色,而相邻的侧是不同的颜色。问你能形成的总矩形面积之和最大值为多少?
解题思路: 由于很多信息我们都不明了,我们对于这个问题会比较模糊。但我们仔细想想我们求总矩形面积之和的最大值问题(即最优解)是不是可以转换为更小的子问题?设我们可以构造的最大矩形数为,(注意:最大矩形数是一定固定的)那么该状态的最优解是不是可以转换为矩形数为的最优解+当前可构建矩形面积的最大值。我们用表示用去了个R颜色彩棒,个G个颜色彩棒,个C颜色彩棒,那么我们表示矩形数为自然对应的彩棒数要减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;
}