題解:CF1209E1 Rotate Columns (easy version)

Adventurer_XIV發表於2024-08-09

題目傳送門

題意

給出一個 \(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;
}

相關文章