题意
给出一个 \(n\times m\) 的矩阵,我们可以对每一列进行循环位移,不限次数,最后求每一行的最大值之和。
\(1 \leq n \leq 4 , 1 \leq m \leq 100\)
思路
注意到 \(n\) 的范围很小,那么我们也可以缩小 \(m\) 的范围。
正确的方案显然是取整个矩阵的前 \(n\) 大值,并且将它们换到每一行。即便这 \(n\) 大值分布在不同的列,也一共只有 \(n\) 列,因此整个矩阵的有效范围只有 \(n \times n\)。
现在就可以随意的爆搜了,对于每一列,循环枚举位移的行数,最后统计答案即可,注意多测要清空。
代码
#include<bits/stdc++.h>
#define int long long
#define inf 0x7f7f7f7f
using namespace std;
int lst[105][105][105],T,n,m;
int maxx[105],ans=-inf;
struct MRS{
int sr[105],maxn;//sr存行
bool operator<(const MRS &x){return maxn>x.maxn;}
}mp[105];//存列
bool cmp(int a,int b){return a>b;}
void dfs(int x){
if(x>n){//搜索结束
int sum=0;
for(int i=1;i<=n;i++)sum+=maxx[i];
ans=max(ans,sum);
return;
}
for(int i=0;i<=n-1;i++){
for(int j=1;j<=n;j++){
int tmp=((i+j)==n)?(i+j):(i+j)%n;//注意当下标等于n时不取余
lst[x][i][tmp]=maxx[tmp];//记录当前情况
maxx[tmp]=max(maxx[tmp],mp[x].sr[j]);//更新
}
dfs(x+1);
for(int j=1;j<=n;j++)maxx[j]=lst[x][i][j];//回溯
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>T;
while(T--){
ans=0;
memset(mp,0,sizeof(mp));
memset(lst,0,sizeof(lst));
memset(maxx,0,sizeof(maxx));
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)cin>>mp[j].sr[i],mp[j].maxn=max(mp[j].maxn,mp[j].sr[i]);//存储每一列的的最大值,之后按此排序
sort(mp+1,mp+1+m);
dfs(1);
cout<<ans<<'\n';
}
return 0;
}
标签:Rotate,leq,int,题解,CF1209E1,maxn,mp,sr,105
From: https://www.cnblogs.com/MithrilSwordXIV/p/18351402