zoukankan      html  css  js  c++  java
  • Codeforces Round #FF/#255 D DZY Loves Modification --贪心+优先队列

    题意:给你一个矩阵,每次选某一行或者某一列,得到的价值为那一行或列的和,然后该行每个元素减去p。问连续取k次能得到的最大总价值为多少。

    解法:

    如果p=0,即永远不减数,那么最优肯定是取每行或每列那个最大的取k次,所以最优解由此推出。

    如果不管p,先拿,最后再减去那些行列交叉点,因为每个点的值只能取一次,而交叉点的值被加了两次,所以要减掉1次,如果取行A次,取列B次,那么最后答案为:

    res = dp1[A] + dp2[B] - B*(k-A)*p,可以细细体会一下后面那部分。

    其中:

    dp1[A]表示在行中取A次得到的最大和(取完要减去p哦)

    dp2[B]表示在列中取B次得到的最大和(~)

    每次取最大的可以用优先队列来实现,思想就是这么个思想。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #include <queue>
    #define lll __int64
    using namespace std;
    #define N 1007
    #define M 33
    
    lll dp1[N*N],dp2[N*N];
    lll RS[N],CS[N];
    lll a[N][N];
    priority_queue<lll> que;
    
    int main()
    {
        int n,m,k,p;
        int i,j;
        while(scanf("%d%d%d%d",&n,&m,&k,&p)!=EOF)
        {
            memset(RS,0,sizeof(RS));
            memset(CS,0,sizeof(CS));
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=m;j++)
                {
                    scanf("%I64d",&a[i][j]);
                    RS[i] += a[i][j];
                    CS[j] += a[i][j];
                }
            }
            dp1[0] = dp2[0] = 0;
            while(!que.empty())
                que.pop();
            for(i=1;i<=n;i++)
                que.push(RS[i]);
            for(i=1;i<=k;i++)
            {
                lll tmp = que.top();
                que.pop();
                dp1[i] = dp1[i-1]+tmp;
                tmp -= (lll)m*p;
                que.push(tmp);
            }
            while(!que.empty())
                que.pop();
            for(i=1;i<=m;i++)
                que.push(CS[i]);
            for(i=1;i<=k;i++)
            {
                lll tmp = que.top();
                que.pop();
                dp2[i] = dp2[i-1]+tmp;
                tmp -= (lll)n*p;
                que.push(tmp);
            }
            ll res = dp1[0]+dp2[k];
            for(i=1;i<=k;i++)
            {
                ll tmp = dp1[i]+dp2[k-i]-1LL*i*(k-i)*p;
                res = max(res,tmp);
            }
            printf("%I64d
    ",res);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Vue3.0官方文档
    简单实现Vue的双向绑定原理
    小程序使用weapp-qrcode二维码插件,宽高自适应解决方法
    小程序判断ios还是android
    手写实现bind
    手写实现call,apply函数
    React onClick点击事件传参三种写法
    zynq 中断
    zynq_ps端点亮led灯代码
    突然发现自己的很多博客无法显示图片,人都傻了,于是就整理了一早上,全部换成了markdown格式,就好了,希望博客的时间不会对大家造成困扰!!!
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3841984.html
Copyright © 2011-2022 走看看