題目傳送門
題意
給出一個 \(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;
}