UVA 10827 Maximum sum on a torus

算法入门经典训练指南88页练习

::这道题只要把原矩阵扩大4倍,那么其跟最大子矩阵的题目就很类似,把二维转化成一维,求最大的序列和,不过这个序列的长度不能超过n。

长度不能超过n? 那这道题又跟hdu 3415 HDU 3415 Max Sum of Max-K-sub-sequence (单调队列)

 

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <algorithm>

 5 #include <queue>

 6 using namespace std;

 7 #define REP(i,n) for(int i=0; i<(n); i++)

 8 #define FOR(i,s,t) for(int i=(s); i<=t; i++)

 9 typedef long long ll;

10 const int INF = 1<<30;

11 const int N = 155;

12 int S[N][N],n,_;

13 int sum[N];

14 

15 void show(){

16     FOR(i,1,2*n){

17         FOR(j,1,2*n)

18             printf("%4d",S[i][j]);

19         cout<<endl;

20     }

21 }

22 

23 void solve(){

24     scanf("%d", &n);

25 

26     //矩阵扩大

27     FOR(i,1,n) FOR(j,1,n){

28          scanf("%d", &S[i][j]);

29          S[i+n][j] = S[i][j];

30          S[i][j] += S[i-1][j];

31          S[i][j+n] = S[i][j];

32 

33     }

34     FOR(i,n+1,2*n) FOR(j,1,n){

35         S[i][j] += S[i-1][j];

36         S[i][j+n] = S[i][j];

37     }

38 

39     int ans = -INF;

40     FOR(i,0,n) FOR(j,i+1,i+n){//枚举上下边界,从右往左扫描

41          int q[N<<1],head=0,tail=0;

42          for(int k = 1; k<2*n; k++){

43              sum[k] =S[j][k] - S[i][k] + sum[k-1];

44              while(tail>head && sum[k] <= sum[q[tail]]) tail--;//用单调队列优化

45              q[++tail] = k;

46              while(tail>head && k - q[head+1]>n) head++;

47              ans  = max(ans , sum[k] - sum[q[head+1]]);

48          }

49     }

50     printf("%d\n",ans);

51 }

52 

53 int main(){

54 //    freopen("in.txt","r",stdin);

55     scanf("%d", &_);

56     while(_--) solve();

57     return 0;

58 }

 

你可能感兴趣的:(uva)