CF Spiral Maximum

来源:互联网 发布:国内互联网网络股票 编辑:程序博客网 时间:2024/06/05 04:28

这是一个好题。

刚开始看没想深,没发现什么规律,感觉得直接爆,但这会超时。后来仔细想了想,奥秘就在这螺旋中。

由3层螺旋的值,可以得到5层螺旋的值,依次类推,条件是中心不变,依次向外扩。

那么如何由3层值得到5层值呢?假设3层值为A,扩到5层后,假设5层内的所有值的和为B,则5层螺旋的值为B-A,是不是很神奇,至于为什么是,你用笔画画就知道了,其余层数依次类推。

我们可以O(n^2)的预处理,求出各个点的和,然后O(n^2*k)来求最优值。其中n^2来枚举,k是每个点的扩展层数之和,我也估不出是多少,在极限情况下是250,但也是极限情况下一个点这样,平均情况应该远远小于这个值,没有别的方法,只能试试。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;int mat[510][510], sum[510][510];int n, m;bool ok(int x, int y){    if(x >= 0 && x < n && y >= 0 && y < m)        return true;    return false;}int main(){    //freopen("input.txt", "r", stdin);    scanf("%d %d", &n, &m);    for(int i = 0; i < n; i++)        for(int j = 0; j < m; j++)            scanf("%d", &mat[i][j]);    memset(sum, 0, sizeof(sum));    for(int i = n - 1; i >= 0; i--){        int t = 0;        for(int j = m - 1; j >= 0; j--){            t += mat[i][j];            sum[i][j] = sum[i + 1][j] + t;        }    }    int ans = -1000000000;    for(int i = 1; i < n; i++){        for(int j = 1; j < m; j++){            int x = i, y = j;            int t = mat[i][j];            int l = 1;            while(true){                x--, y--;                l += 2;                if(ok(x, y) && (x + l - 1) < n && (y + l - 1) < m){                    t += mat[x + 1][y];                    int s = sum[x][y] - sum[x + l][y] - sum[x][y + l] + sum[x + l][y + l];                    t = s - t;                    ans = max(ans, t);                }else break;            }        }    }    printf("%d\n", ans);    return 0;}


原创粉丝点击