贪心 · 例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;
 
}
posted @ 2025-03-26 21:36  awei040519  阅读(22)  评论(0)    收藏  举报