题目链接
http://poj.org/problem?id=2078
题意
输入一个n×n的矩阵,可以对矩阵的每行进行任意次的循环右移操作,行的每一次右移后,计算矩阵中每一列的和的最大值,输出这些最大值中的最小值。
思路
使用dfs解决,对于n×n的矩阵来说,行循环右移后,矩阵最多有n^n中可能的状态,在这题中最多有7^7=823543中状态,是可以暴力搜索的。使用dfs搜索这些状态,并计算矩阵每个状态的列和的最大值,输出最大值中的最小值即可。
代码
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int INF = 1<<30; 7 8 const int N = 10; 9 int a[N][N]; 10 int n; 11 int minNum; 12 13 void rotate(int r) //对行a[r][]循环右移一次 14 { 15 int t = a[r][n-1]; 16 for(int i=n-1; i>0; i--) 17 a[r][i] = a[r][i-1]; 18 a[r][0] = t; 19 } 20 21 void dfs(int r) 22 { 23 int maxNum = -INF; //列和的最大值 24 if(r==n) 25 { 26 for(int j=0; j<n; j++) 27 { 28 int sum = 0; 29 for(int i=0; i<n; i++) 30 sum += a[i][j]; 31 if(sum>maxNum) 32 maxNum = sum; 33 } 34 if(maxNum<minNum) 35 minNum = maxNum; //保存列和最大值中的最小值 36 } 37 else 38 { 39 for(int i=0; i<n; i++) //每一行都循环右移n次 40 { 41 rotate(r); 42 dfs(r+1); 43 } 44 } 45 } 46 47 int main() 48 { 49 //freopen("poj2078.txt", "r", stdin); 50 while(cin>>n) 51 { 52 if(n==-1) 53 return 0; 54 55 memset(a, 0, sizeof(a)); 56 for(int i=0; i<n; i++) 57 for(int j=0; j<n; j++) 58 cin>>a[i][j]; 59 60 minNum = INF; 61 dfs(1); //从第1行开始搜索可以节省时间 62 cout<<minNum<<endl; 63 } 64 return 0; 65 }
注意点
1、由于矩阵的循环右移是相对的,所以第0行不动,从第1行开始搜索会节省时间,从第0行开始搜索(dfs(0);)也可以通过,但花费的时间会长一些。