51nod 1625 夹克爷发红包

来源:互联网 发布:整站源码下载工具 编辑:程序博客网 时间:2024/06/02 11:00

开始呢,做的时候是选取最小的列和最小的行,然后谁小就替换谁,wa了,想了下,如果每替换一行或一列,就去修改所有受影响的行和列,是不是有点太麻烦了。就网上搜了下:http://blog.csdn.net/f_zyj/article/details/52216205
行最多只有10行,所有的状态一共最多也就1024种,可以把行的这些状态全都枚举出来,选出符合条件的,再去贪心的选取替换哪些列。

#include <bits/stdc++.h>using namespace std;typedef long long LL;const int MAXR = 12;const int MAXC = 210;LL G[MAXR][MAXC];LL RM[MAXR];LL CM[MAXC];vector<LL> h;LL Sum = 0;LL calc(LL num){    LL res = 0;    while(num)    {        if(num&1) ++res;        num >>= 1;    }    return res;}bool cmp(const LL& a, const LL& b){    return a > b;}int main(){    LL n,m,x,k;    cin >> n >> m >> x >> k;    h.resize(m,0);    for(LL i = 0; i < n; ++i)    {        for(LL j = 0; j < m; ++j)        {            cin >> G[i][j];            RM[i] += G[i][j];            CM[j] += G[i][j];            Sum += G[i][j];        }    }    LL rowMax = x*m;    LL colMax = x*n;    LL Ceil = 1LL<<n;    LL ans = Sum;    for(LL i = 0; i < Ceil; ++i)    {        LL ret = Sum;        LL cnt = calc(i);        if(cnt > k) continue;        vector<int> record;        for(int r = 0; r < n; ++r)//计算出替换行后的收益        {            if((i>>r)&1)            {                ret += rowMax - RM[r];                record.push_back(r);            }        }        for(int j = 0; j < m; ++j)//计算替换每一列所得的收益        {            h[j] = colMax - CM[j];            for(int k = 0; k < record.size(); ++k)                h[j] += G[record[k]][j]-x;        }        sort(h.begin(),h.end(),cmp);//将收益降序排序,选取大的收益        for(int j = 0; j+cnt < k && h[j] > 0; ++j)//负的收益不要            ret += h[j];        ans = max(ret,ans);    }    cout << ans << endl;    return 0;}
原创粉丝点击