题解:CF1209E1 Rotate Columns (easy version)

题目传送门

题意

给出一个 \(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;
}
posted @ 2024-08-09 19:51  MrSWdAxiv  阅读(34)  评论(0)    收藏  举报