• Codeforces 1398D



    1398D. Colored Rectangles

    题意

    给定三个集合({R},{G},{B})

    要求每次任选两个集合分别取出一个数字,相乘后加入答案

    问答案最大可能是多少


    限制

    Time limit per test: 2 seconds

    Memory limit per test: 256 megabytes

    (1leq R,G,Bleq 200)

    (1leq r_i,g_i,b_ileq 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 { egin{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} ight } ]

    最后处理下边界情况即可

    注意每次转移就尝试更新答案




    完整程序

    (93ms/2000ms)

    #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<<'
    ';
    }
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        solve();
        return 0;
    }
    

  • 相关阅读:
    linux安装软件的几种方式
    linux目录
    linux远程连接
    linux分区
    linux特殊符号
    sed
    rest_framework认证流程
    一些面试题目
    算法之二分法
    算法之动态规划
  • 原文地址:https://www.cnblogs.com/stelayuri/p/13508132.html
Copyright © 2020-2023  润新知