codeforces 1209E1 Rotate Columns (easy version)
題目傳送門:codeforcces , luogu
思路
貪心,暴力搜尋
貪心
對於所有列,只有列中最大值在所有列的最大值中前 \(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;
}