• 小奇的矩阵


    【问题描述】
    给定一个 n*m 的矩阵,矩阵中的每个元素 aij 为正整数。
    接下来规定
    1.合法的路径初始从矩阵左上角出发,每次只能向右或向下走,终点为右下
    角。
    2.路径经过的 n+m-1 个格子中的元素为 A1,A2...A(n+m-1),Aavg 为 Ai 的平
    均数,路径的 V 值为(n+m-1)*∑(Ai-Aavg) ^2
    (1<=i<=n+m-1)
    求 V 值最小的合法路径,输出 V 值即可,有多组测试数据。
    【输入格式】
    第一行包含一个正整数 T,表示数据组数。
    对于每组数据:
    第一行包含两个正整数 n 和 m,表示矩阵的行数和列数。
    接下来 n 行,每行 m 个正整数 aij,描述这个矩阵。
    【输出格式】
    对于每次询问,输出一行一个整数表示要求的结果
    【样例输入】
    1
    2 2
    1 2
    3 4
    【样例输出】
    14
    【数据范围】
    对于 30%的数据 n<=10,m<=10
    有另外 40%的数据 n<=15 m<=15,矩阵中的元素不大于 5
    对于 100%的数据 T<=5,n<=30,m<=30,矩阵中的元素不大于 30

    把式子化简:

    ans=(n-m+1)∑Ai2-sum2

    但这个式子并不是Ai越小越好

    于是dp

    令f[i][j][k]表示到(i,j)路径和为k,路径的平方和

    于是答案就是(n-m+1)*f[n][m][i]-i2

    考试时傻逼,把求和的变量忘了清0,后来直接赋为(n+m)*30

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 long long n,m;
     7 long long a[35][35],f[35][35][2001],inf,s,ans;
     8 long long min(long long a,long long b)
     9 {
    10     if (a<b) return a;
    11     return b;
    12 }
    13 int main()
    14 {
    15     int T;
    16     long long i,j,k;
    17     cin>>T;
    18     while (T--)
    19     {
    20         scanf("%lld%lld",&n,&m);
    21         s=0;
    22         for (i=1; i<=n; i++)
    23             for (j=1; j<=m; j++)
    24                 scanf("%lld",&a[i][j]),s+=a[i][j];
    25         memset(f,127/2,sizeof(f));
    26         inf=f[0][0][0];
    27         f[1][1][a[1][1]]=a[1][1]*a[1][1];
    28         for (i=1; i<=n; i++)
    29         {
    30             for (j=1; j<=m; j++)
    31             {
    32                 if (i==1&&j==1) continue;
    33                 for (k=0; k<=(n+m)*30; k++)
    34                 {
    35                     long long x=a[i][j]*a[i][j];
    36                     if (i>1) f[i][j][k+a[i][j]]=min(f[i][j][k+a[i][j]],f[i-1][j][k]+x);
    37                     if (j>1) f[i][j][k+a[i][j]]=min(f[i][j][k+a[i][j]],f[i][j-1][k]+x);
    38                 }
    39             }
    40         }
    41         ans=inf;
    42         for (i=0; i<=(m+n)*30; i++)
    43             if (f[n][m][i]!=inf)
    44                 ans=min(ans,f[n][m][i]*(n+m-1)-i*i);
    45         cout<<ans<<endl;
    46     }
    47 }
  • 相关阅读:
    洛谷.3254.圆桌问题(最大流ISAP)
    BZOJ.2639.矩形计算(二维莫队)
    BZOJ.2724.[Violet 6]蒲公英(静态分块)
    BZOJ.4241.历史研究(回滚莫队 分块)
    BZOJ.4542.[HNOI2016]大数(莫队)
    SPOJ.COT2 Count on a tree II(树上莫队)
    BZOJ.3757.苹果树(树上莫队)
    洛谷.2325.[SCOI2005]王室联邦(贪心)
    BZOJ.1299.[LLH邀请赛]巧克力棒(博弈论 Nim)
    HDU.2516.取石子游戏(博弈论 Fibonacci Nim)
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7766622.html
Copyright © 2020-2023  润新知