codeforces 1209E1 Rotate Columns (easy version)

题目传送门:codeforccesluogu

思路

贪心,暴力搜索

贪心

对于所有列,只有列中最大值在所有列的最大值中前 \(n\) 大才可能对答案有贡献。
证明:若有非前 \(n\) 大的列对某行最大值产生了贡献,则用没有被取的前 \(n\) 大的列代替该行一定更优。所以只有列中最大值在所有列的最大值中前 \(n\) 大才可能对答案有贡献。

暴力搜索

将所有列按列的最大值从大到小排序。根据贪心,答案一定由前 \(n\) 列产生,而 \(n \leq 4\) ,所以直接爆搜就行了。

细节

更新的时候要先保存,不然回溯会出错。

代码

单次时间复杂度\(O(n^{2 \times n - 2})\)

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int N = 6, M = 105;

#define LF(i, __l, __r) for (int i = __l; i <= __r; i++)
#define RF(i, __r, __l) for (int i = __r; i >= __l; i--)

struct col { int a[N], mx; } a[M];
int t, n, m, ans, mx[N];
int back[N][N][N];

bool cmp(col a, col b) { return a.mx > b.mx; }

void Init() {
    ans = 0;
    memset(mx, 0, sizeof(mx));
    memset(back, 0, sizeof(back));
    memset(a, 0, sizeof(a));
}

void dfs(int u) {
    if (u == n + 2) {
        int res = 0;
        LF(i, 1, n) res += mx[i];
        ans = max(ans, res);
        return;
    }

    LF(i, 0, n - 1) {
        LF(j, 1, n) {
            int s = i + j;
            if (s > n) s %= n;
            back[u][i][s] = mx[s];
            mx[s] = max(mx[s], a[u].a[j]);
        }
        dfs(u + 1);
        LF(j, 1, n) mx[j] = back[u][i][j];
    }
}

int main() {
    scanf("%d", &t);

    while (t--) {
        Init();
        scanf("%d%d", &n, &m);
        LF(i, 1, n) LF(j, 1, m) {
            scanf("%d", &a[j].a[i]);
            a[j].mx = max(a[j].mx, a[j].a[i]);
        }

        sort(a + 1, a + m + 1, cmp);
        
        dfs(1);
        printf("%d\n", ans);
    }
    return 0;
}

它山之石,可以攻玉。——《诗经·小雅》

posted @ 2024-07-28 16:00  FRZ_29  阅读(2)  评论(0编辑  收藏  举报