UVA 10827 Maximum sum on a torus (LA)

算法入门经典训练指南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 }

 

posted @ 2014-05-29 23:17  ForeverEnjoy  阅读(210)  评论(0编辑  收藏  举报