1. 程式人生 > 實用技巧 >Codeforces 1398D - Colored Rectangles (dp)

Codeforces 1398D - Colored Rectangles (dp)


1398D. Colored Rectangles

題意

給定三個集合\(\{R\},\{G\},\{B\}\)

要求任選兩個集合分別取出一個數字,相乘後加入答案

問答案最大可能是多少


限制

Time limit per test: 2 seconds

Memory limit per test: 256 megabytes

\(1\leq R,G,B\leq 200\)

\(1\leq r_i,g_i,b_i\leq 2000\)




考慮動態規劃

貪心可得,每次取出的兩個數一定是對應集合內最大的數字

所以先按照數值從大到小排序

\(dp[i][j][k]\)表示\(\{R\}\)集合中取了(前)\(i\)

個數,\(\{G\}\)集合中取了(前)\(j\)個數,\(\{B\}\)集合中取了(前)\(k\)個數後的最大可能答案

那麼我們考慮轉移到當前狀態的情況

如果當前狀態是由取出\(\{R\},\{G\}\)兩個集合的元素得到的,那麼\(dp[i][j][k]=dp[i-1][j-1][k]+a[i]*b[j]\)

如果當前狀態是由取出\(\{R\},\{B\}\)兩個集合的元素得到的,那麼\(dp[i][j][k]=dp[i-1][j][k-1]+a[i]*c[k]\)

如果當前狀態是由取出\(\{G\},\{B\}\)兩個集合的元素得到的,那麼\(dp[i][j][k]=dp[i][j-1][k-1]+b[j]*c[k]\)

由於答案要取最值,先忽略邊界情況,則得到的狀態轉移方程為

\[dp[i][j][k]=max \left \{ \begin{aligned} dp[i-1][j-1][k]+a[i]*b[j]\\ dp[i-1][j][k-1]+a[i]*c[k]\\ dp[i][j-1][k-1]+b[j]*c[k] \end{aligned} \right \} \]

最後處理下邊界情況即可

注意每次轉移就嘗試更新答案




完整程式

(啊還沒終測呢……)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int a[222],b[222],c[222];
ll dp[222][222][222];

void solve()
{
    int R,G,B;
    cin>>R>>G>>B;
    for(int i=1;i<=R;i++)
        cin>>a[i];
    for(int i=1;i<=G;i++)
        cin>>b[i];
    for(int i=1;i<=B;i++)
        cin>>c[i];
    sort(a+1,a+1+R,greater<int>());
    sort(b+1,b+1+G,greater<int>());
    sort(c+1,c+1+B,greater<int>());
    memset(dp,-0x3f,sizeof dp);
    dp[0][0][0]=0;
    ll ans=0;
    for(int i=0;i<=R;i++) //注意從0開始列舉
        for(int j=0;j<=G;j++)
            for(int k=0;k<=B;k++)
            {
                if(i&&j&&k) //四種可轉移的情況
                    dp[i][j][k]=max(dp[i-1][j-1][k]+a[i]*b[j],max(dp[i-1][j][k-1]+a[i]*c[k],dp[i][j-1][k-1]+b[j]*c[k]));
                else if(i&&j)
                    dp[i][j][k]=dp[i-1][j-1][k]+a[i]*b[j];
                else if(i&&k)
                    dp[i][j][k]=dp[i-1][j][k-1]+a[i]*c[k];
                else if(j&&k)
                    dp[i][j][k]=dp[i][j-1][k-1]+b[j]*c[k];
                ans=max(ans,dp[i][j][k]);
            }
    cout<<ans<<'\n';
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}