題目大意
:一個n*n的數字矩陣,每次操作可以對任意一行或者一列進行循環移動,操作次數任意。求每種情況每一列的最大值的最小值。
思路分析
輸入一個方陣,可以對矩陣的每一行進行任意次的右移操作,求出位移後的矩陣每列的最大值,然後多次位移,得到多組最大值,最後求出這些最大值中的最小值。關鍵還是排列組合的問題,對於一個n*n的矩陣來說,第一行位移有n種形式,第二行也有n種,以此類推,故總的有種矩陣的形態。可以利用dfs搜索出這些狀態,固定當前的行,去遞歸調用剩餘的行,進而計算出每種矩陣形態的值。由於矩陣的右移是相對的,所以可以直接從第二行直接搜索,也就是說一共只有種不同形態。節省時間。
//156K 516MS
#define inf 0x3f3f3f3f
#define ll long long
#define vec vector<int>
#define P pair<int,int>
#define MAX 10
int n, a[MAX][MAX], x[MAX], res = inf;
string s[MAX];
//到了第k行
void dfs(int k) {
if (k == n) {//根據反轉統計結果
int ma = 0;
for (int j = 0; j < n; j++) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += a[i][s[i][j] - '0'];//行是對的,列是改變過的
}
if (sum > ma)ma = sum;
}
if (ma < res)res = ma;
return;
}
for (int i = 0; i < n; i++) {
s[k] = s[k].substr(1) + s[k][0];//兩極反轉
dfs(k + 1);
}
}
int main() {
while (scanf("%d", &n) && n != -1) {
string t;
for (int i = 0; i < n; i++)t += i + '0';
for (int i = 0; i < n; i++) {
s[i] = t;
for (int j = 0; j < n; j++)
scanf("%d", &a[i][j]);
}
res = inf;
dfs(1);
cout << res << endl;
}
}