贪心 · 例5-矩阵消除游戏(二进制转换+贪心)
我们可以用01串来表示状态,比如01001表示134行不选,第25行选择,这样我们直接枚举0到2^n - 1就代表枚举了00…00到11…11
大致过程:
T从0~2^n - 1枚举,表示行的状态
T是一个十进制数,我们转发成二进制,看里面几个1(numh),哪些位置是1,进行记录。
T中几个1说明选几行,numl=k-numh(T中1的个数)为选几列
sum先加上要选的那几行(T中1的位置)
然后刨去那几行的数据,我们对剩下的数据按照每列的和进行排序,选择最高的那numl列
维护答案即可
整个过程实则为二进制转换+贪心
贪心 · 例5-矩阵消除游戏
#include<bits/stdc++.h>
using namespace std;
int n, m ,k;
int a[20][20];
long long row[20], col[20];//sh[i]是第i行的和,sl[i]是第i列的和(在行选完之后用)
bool st[20];
long long ans, sum;
int deal(int x){
memset(st, 0, sizeof st);
int cnt = 0, index = 1;
while(x){
if(x&1){
++cnt;
st[index] = 1;
}
x >>= 1;
++index;
}
return cnt;
}
bool cmp(int a, int b){
return a > b;
}
signed main(){
cin >> n >> m >> k;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
cin >> a[i][j];
row[i] += a[i][j];
sum += a[i][j];
}
if(k >= n || k >= m) {cout << sum << endl; return 0;}
//—————枚举选行的所有可能性,贪心处理列——————
int tmp = (1 << n) - 1;
for(int i = 0; i <= tmp; ++i){
int numrow = deal(i);
int numcol = k - numrow;
if(numcol < 0 || numcol > m) continue;
sum = 0;
for(int j = 1; j <= n; ++j)
if(st[j]) sum += row[j];
memset(col, 0, sizeof col);
for(int j = 1; j <= n; ++j)
for(int k = 1; k <= m; ++k)
if(!st[j]) col[k] += a[j][k];
sort(col + 1, col + 1 + m, cmp);
for(int j = 1; j <= numcol; ++j) sum += col[j];
ans = max(ans, sum);
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号