SSL2841 2017年11月7日提高组T2 好路线(dp)

来源:互联网 发布:如何提升淘宝搜索排名 编辑:程序博客网 时间:2024/05/16 18:58

2017年11月7日提高组T2 好路线

Description

nodgd在旅游。现在,nodgd要从城市的西北角走到东南角去。这个城市的道路并不平坦,nodgd希望找出一条相对比较好走的路。
nodgd事先已经得到了这个城市的地图。地图上这个城市是一个n×m的矩形,nodgd现在站在坐标为(1,1)的位置,需要到达坐标为(n,m)的位置。这张地图上用非负整数标记了每个整数坐标点的海拔,坐标为(x,y)的位置的海拔是h(x,y)。nodgd希望找出一条路线,路线中任意时刻都在向正东或向正南走,而且只在整数坐标点的地方转弯,使得路上经过的n+m-1个整数坐标点的海拔的方差最小。然而万能的nodgd当然知道该怎么走,也当然知道方差最小是多少,只是想顺便考考你。
假如有k个实数x1,x2,…,xk,则平均值定义为
这里写图片描述

在本题中为了方便,你只需要求出(n+m-1)^2*方差的最小值即可,众所周知这是个整数。

Input

第一行输入两个整数n,m,表示城市的大小。
接下来n行,每行m个数,其中第i行第j个数就是h(i,j)。

Output

输出一行一个整数,表示(n+m-1)^2*方差的最小值。

Sample Input

2 2
1 2
3 4
Sample Output

14
Hint

对于30%的数据,1≤n,m≤10;
对于50%的数据,1≤n,m≤20;
对于100%的数据,1≤n,m≤50,0≤h(x,y)≤50。

分析:通过将该式子化简可知n*Σxi^2-(Σxi)^2
因此定义dp[i][j][k]表示到i j时总和为k的最小n*Σxi^2,最后答案减去(Σxi)^2 即可。

代码

#include <cstdio>#define N 60#define ll long longusing namespace std;ll f[N][N][N*100],a[N][N],n,m;ll fsqr(ll x){    return x*x;}ll min(ll x,ll y){    return x<y?x:y;}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("%lld",&a[i][j]);    for (int i=1;i<=n;i++)        for (int j=1;j<=m;j++)            for (int k=0;k<=(n+m-1)*50;k++)                f[i][j][k]=1e9;    f[1][1][a[1][1]]=fsqr(a[1][1]);    for (int i=1;i<=n;i++)        for (int j=1;j<=m;j++)            for (int k=0;k<=(n+m-1)*50;k++)            {                if (f[i][j][k]==1e9) continue;                int dx,dy;                dx=i;dy=j+1;                f[dx][dy][k+a[dx][dy]]=min(f[dx][dy][k+a[dx][dy]],f[i][j][k]+fsqr(a[dx][dy]));                dx=i+1;dy=j;                f[dx][dy][k+a[dx][dy]]=min(f[dx][dy][k+a[dx][dy]],f[i][j][k]+fsqr(a[dx][dy]));            }    ll ans=1e9;    for (int i=0;i<=(n+m-1)*50;i++)        ans=min(ans,f[n][m][i]*(n+m-1)-fsqr(i));    printf("%lld",ans);    fclose(stdin);    fclose(stdout);}