zoukankan      html  css  js  c++  java
  • 常州day1p5

    给一个 n∗m 的矩阵,矩阵的每个格子上有一个不超过 30 的非负整数。 我们定义一条合法的路线是从(1,1)开始只能向右和向下移动到达(n,m)的路线。 定义数列 A1,A2,A3,..,An+m−1 为一条合法路线上的序列,且 Aavg 为该数列的平均值。该路线的 价值为 (n + m−1) 乘上该数列的方差。 即价值的表达式为 (n + m−1)∑n+m−1 i=1 (Ai−Aavg)2。 请找一条价值最小的路线,并输出这个价值。 

    对于 100% 的数据,n,m,ai,j ≤ 30

    我们发现对于一条确定的路径sigma((a[i]-s)^2)是一个关于s的二次函数,而方差是二次函数的最低点

    在数据大的时候会有很多的二次函数,这些二次函数最低点的最小的那个就是答案

    这些二次函数的最小值大概会形成一个类似单谷函数的东西。

    于是三分。

    这是错误的,但是很难卡掉。

    小数据暴力

    时间复杂度 O(n^2logn)

    实际上是标程一个牺牲一定准确性的优化

    #include<stdio.h>
    #include<iostream>
    #include<stdlib.h>
    #include<math.h>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<set>
    #include<map>
    #include<vector>
    #define il inline
    #define re register
    using namespace std;
    typedef double db;
    int n,m,a[101][101],dir[101],b[101];
    db val[101][101],f[101][101];
    il db sqr(db x){return x*x;}
    il void small(){
        db final=1e50;
        for(int S=(1<<(n+m-2))-1;S>=0;--S){
            for(int i=0;i<n+m-2;i++) dir[i]=((S&(1<<i))>0);
            int u=1,v=1,flag=true;
            db ans,cnt=a[1][1];
            for(int i=0;i<n+m-2;i++){
                if(dir[i]) u++;
                else v++;
                if(!(1<=u&&u<=n&&1<=v&&v<=m)){
                    flag=false;break;
                }
                b[i]=a[u][v];cnt+=b[i];
            }
            if(!flag) continue;
            cnt=cnt/(n+m-1);ans=sqr(cnt-a[1][1]);
            for(int i=0;i<n+m-2;i++){
                ans+=sqr(cnt-b[i]);
            }
            final=min(final,ans*(n+m-1));
        }
        printf("%.0lf",final);
    }
    il db res(db ave){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                val[i][j]=sqr(ave-a[i][j]);
        f[1][1]=val[1][1];
        for(int i=2;i<=m;i++) f[1][i]=f[1][i-1]+val[1][i];
        for(int i=2;i<=n;i++) f[i][1]=f[i-1][1]+val[i][1];
        for(int i=2;i<=n;i++){
            for(int j=2;j<=m;j++)
                f[i][j]=min(f[i-1][j],f[i][j-1])+val[i][j];
        }
        return f[n][m]*(n+m-1);
    }
    int main(){
        freopen("route.in","r",stdin);
        freopen("route.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]);
        if(n+m<=20){
            small();exit(0);
        }
        db l=0,r=30,m1,m2;
        for(int i=1;i<=100;i++){
            m1=(r-l)/3+l;
            m2=r-(r-l)/3;
        //    cout<<l<<" "<<m1<<" "<<m2<<" "<<r<<endl;
            if(res(m1)<res(m2)) r=m2;
            else l=m1;
        }
        printf("%.0lf",res((l+r)/2));
        return 0;
    }
    蜉蝣渴望着飞翔,尽管黄昏将至
  • 相关阅读:
    Tomcat 三种运行方式
    MariaDB介绍
    Nginx 平滑升级
    代理命令 proxy_pass 详解
    Nginx 和 Tomcat 负载均衡
    基于Apache和tomcat实现负载均衡
    centos7 通过源码编译的方式安装和配置Apache
    基于nginx结合openssl实现https
    HTTP 和 HTTPS 区别
    linux系统中修改别名配置文件,构建命令别名
  • 原文地址:https://www.cnblogs.com/ExiledPoet/p/5771126.html
Copyright © 2011-2022 走看看