51nod 1625 夹克爷发红包

xiaoxiao2021-02-28  130

开始呢,做的时候是选取最小的列和最小的行,然后谁小就替换谁,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; }
转载请注明原文地址: https://www.6miu.com/read-18012.html

最新回复(0)