bzoj1723 [ Usaco2009 Feb ] --前缀和(水题)

题目大意:

你难以想象贝茜看到一只妖精在牧场出现时是多么的惊讶.她不是傻瓜,立即猛扑过去,用她那灵活的牛蹄抓住了那只妖精.
    “你可以许一个愿望,傻大个儿!”妖精说.
    “财富,”贝茜用梦游般的声音回答道,  “我要获得财富的机会.”
    妖精从来没有碰到过这么简单的愿望.他在地方划出一大块N×N(1≤N≤200)的方格,每个格子上写上_1,000,000到1,000,000之间的数字.他说:  “在方格上朝一个方向行走,可以是行的方向,列的方向,斜对角的方向,一步只能走一格,所有你踩过的数字的和就是你的财富.”
    贝茜请你来帮忙,找到一行、一列或一条对角线上找一段连续的数字,它们的和最大.由于妖精方格的神奇特性,沿着一个方向走,走到了边际,再一步跨过去可以“绕”到方格的对边出现.一行两端的格子是相邻的,一列两端的格子也是相邻的,甚至相邻两行的分别两端的格子也是相邻的(斜对角方向).
    对于下图左边的方格,所有标记过的数字都在一条对角线上.
  
 
对于这个方格,能踩出来的最大的和是24,踩过的数字在右图中标记出来了
 
思路:

我们可以维护行、列、对角线的前缀和,每次用当前和减去最小和、总和减去最小和更新答案。
由于行、列、对角线互不影响,O(n^2)枚举就可以了。
 
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 201
inline char Nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    if(p1==p2){
        p2=(p1=buf)+fread(buf,1,100000,stdin);
        if(p1==p2)return EOF; 
    }
    return *p1++;
}
inline void Read(int& x){
    char c=Nc(),b=1;
    for(;c<'0'||c>'9';c=Nc())if(c=='-')b=-1;
    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=Nc());x*=b;
}
int i,j,k,n,x[N][N],y[N][N],a[N][N],b[N][N],Ans=-1000000,Mix[N],Miy[N],Mia[N],Mib[N],Max[N],May[N],Maa[N],Mab[N];
int main()
{
    Read(n);
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++){
        Read(k);
        x[i][j]=x[i][j-1]+k;
        y[j][i]=y[j][i-1]+k;
        a[(i-j+n)%n+1][i]=a[(i-j+n)%n+1][i-1]+k;
        b[(i+j)%n+1][i]=b[(i+j)%n+1][i-1]+k;
    }
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++){
        if(x[i][j]-Mix[i]>Ans)Ans=x[i][j]-Mix[i];
        if(y[i][j]-Miy[i]>Ans)Ans=y[i][j]-Miy[i];
        if(a[i][j]-Mia[i]>Ans)Ans=a[i][j]-Mia[i];
        if(b[i][j]-Mib[i]>Ans)Ans=b[i][j]-Mib[i];
        if(x[i][n]-x[i][j-1]+Max[i]>Ans)Ans=x[i][n]-x[i][j-1]+Max[i];
        if(y[i][n]-y[i][j-1]+May[i]>Ans)Ans=y[i][n]-y[i][j-1]+May[i];
        if(a[i][n]-a[i][j-1]+Maa[i]>Ans)Ans=a[i][n]-a[i][j-1]+Maa[i];
        if(b[i][n]-b[i][j-1]+Mab[i]>Ans)Ans=b[i][n]-b[i][j-1]+Mab[i];
        if(x[i][j]<Mix[i])Mix[i]=x[i][j];
        if(y[i][j]<Miy[i])Miy[i]=y[i][j];
        if(a[i][j]<Mia[i])Mia[i]=a[i][j];
        if(b[i][j]<Mib[i])Mib[i]=b[i][j];
        if(x[i][j]>Max[i])Max[i]=x[i][j];
        if(y[i][j]>May[i])May[i]=y[i][j];
        if(a[i][j]>Maa[i])Maa[i]=a[i][j];
        if(b[i][j]>Mab[i])Mab[i]=b[i][j];
    }
    printf("%d",Ans);
    return 0;
}
bzoj1723

 

posted @ 2016-12-22 19:47  gjghfd  阅读(401)  评论(0编辑  收藏  举报