zoukankan      html  css  js  c++  java
  • Codeforces 263E

    Codeforces 263E

    原题
    题目描述:一个(n imes m)的矩阵,每格有一个数,给出一个整数(k),定义函数(f(x, y)):

    [f(x, y)=sum_{i=1}^{n} sum_{j=1}^{m} a_{i, j} cdot max(0, k-|i-x|-|j-y|) (k leq x leq n-k+1, k leq y leq m-k+1) ]

    求使(f(x, y))最大的一个二元对((x, y))

    solution
    我表示只会暴力部分和

    1、(sum_{p=1}^{i} a_{i-p+1, j})

    2、(sum_{p=1}^{k} a_{i-p+1, j}*(k-p+1))

    3、(sum_{p=1}^{k} a_{i-p+1, j+p-1})

    4、以图为例,(k=3, (3, 4))为红色圈住的部分每个数*1
    5、以图为例, (k=3, (3, 4)) 为 $ ( ( 4 + 6 + 7 ) imes 1+ ( 2 + 6 ) imes 2+ 8 imes 3) $

    然后旋转三次, 每次算的时候减去最高那列(图为减去第4列),加起来就是答案了。

    AC的人中好像有更神的算法,就是把图斜着看,那就是求正方形的和了。

    code

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <ctime>
    #include <complex>
    #include <set>
    #include <map>
    #include <stack>
    using namespace std;
    
    const int maxn=1010;
    typedef long long LL;
    
    int n, m, lim;
    int a[maxn][maxn], tmpa[maxn][maxn];
    LL f[maxn][maxn], tmpf[maxn][maxn];
    LL sum[maxn][maxn][7];
    
    void init()
    {
    	scanf("%d%d%d", &n ,&m, &lim);
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    			scanf("%d", &a[i][j]);
    }
    void prepare()
    {
    	int fi=max(n, m);
    	for (int i=1; i<=fi; ++i)
    		for (int j=1; j<=fi; ++j)
    			for (int k=1; k<=5; ++k)
    				sum[i][j][k]=0;
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    		{
    			//row and once
    			sum[i][j][1]=sum[i-1][j][1]+a[i][j];
    			//row and in order
    			LL up=(i-1>=lim? sum[i-1-lim][j][1]:0);
    			sum[i][j][2]=sum[i-1][j][2]-(sum[i-1][j][1]-up)+LL(lim)*a[i][j];
    			//bevel
    			sum[i][j][3]=sum[i-1][j+1][3]+a[i][j];
    			//triangle and once
    			up=(i>=lim? sum[i-lim][j][3]:0);
    			LL L;
    			if (j-1>=lim) L=sum[i][j-lim][3];
    			else
    			L=(i-(lim-(j-1))>0? sum[i-(lim-(j-1))][1][3]:0);
    
    			sum[i][j][4]=sum[i][j-1][4]-(L-up)+sum[i][j][1]-(i>=lim? sum[i-lim][j][1]:0);
    			//triangle and in order
    			sum[i][j][5]=sum[i][j-1][5]-sum[i][j-1][4]+sum[i][j][2];
    		}
    }
    void turn()
    {
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    			tmpa[i][j]=a[i][j];
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    			a[m-j+1][i]=tmpa[i][j];
    
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    			tmpf[i][j]=f[i][j];
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    			f[m-j+1][i]=tmpf[i][j];
    	swap(n, m);
    }
    void solve()
    {
    	for (int i=1; i<=4; ++i)
    	{
    		prepare();
    		for (int j=1; j<=n; ++j)
    			for (int k=1; k<=m; ++k)
    				f[j][k]+=sum[j][k][5]-sum[j][k][2];
    		turn();
    	}
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    			f[i][j]+=a[i][j]*lim;
    
    	int x=0, y=0;
    	LL ans=-1;
    	for (int i=lim; i<=n-lim+1; ++i)
    		for (int j=lim; j<=m-lim+1; ++j)
    			if (f[i][j]>ans)
    			{
    				x=i; y=j;
    				ans=f[i][j];
    			}
    	printf("%d %d
    ", x, y);
    }
    int main()
    {
    	freopen("input.txt", "r", stdin);
    	freopen("output.txt", "w", stdout);
    	init();
    	solve();
    	return 0;
    }
    
    
    
  • 相关阅读:
    ORM 实现数据库表的增删改查
    数据库表设计(一对多,多对多)
    Razor模板引擎
    文件的上传(表单上传和ajax文件异步上传)
    生成验证码封装(新版)
    MD5加密
    反射的一些基本用法
    数据的增删改查(三层)<!--待补充-->
    linux文件的硬连接和软连接
    linux磁盘用满的两种情况
  • 原文地址:https://www.cnblogs.com/GerynOhenz/p/4963241.html
Copyright © 2011-2022 走看看