小奇的矩阵

【问题描述】
给定一个 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 }

 

posted @ 2017-11-01 15:14  Z-Y-Y-S  阅读(420)  评论(0编辑  收藏  举报