题意:给定一个m行n列的矩阵,每列可以进行旋转操作,即列上的元素往上或往下依次循环移动,可以在任意行进行任意次操作,求出操作过后每行的最大元素之和的最大值
思路:可以将每列压缩成一个状态,来存储是否旋转且旋转过多少次,对于每个状态枚举其所有子状态,依次进行旋转操作,求出旋转过后能取到的最大值,再判断是否需要进行旋转
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100+10;
const int inf = 0x3f3f3f3f;
int T, n, m, g[maxn][maxn], dp[maxn][maxn];
int main()
{
cin >> T;
while (T--) {
cin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
cin >> g[i][j];
memset(dp, 0, sizeof(dp));
for (int i = 0; i < m; i++)
for (int j = 0; j < 1<<n; j++) //当前列状态
for (int k = j; ; k = (k-1)&j) { //当前列的所有子状态
int maxx = 0;
for (int r = 0; r < n; r++) { //开始旋转
int cur = 0;
for (int y = 0; y < n; y++) {
int p = (y+r)%n;
if ((j&(1<<p)) && !(k&(1<<p))) //旋转过后是否仍是当前列的子状态,且不是当前所处子状态
cur += g[y][i];
}
maxx = max(maxx, cur); //取当前行各列的最大值
}
dp[i+1][j] = max(dp[i+1][j], dp[i][k] + maxx); //判断是否需要进行旋转
if (k == 0) break;
}
cout << dp[m][(1<<n)-1] << "\n";
}
return 0;
}