NOIP2017模拟赛 好线路(dp)

来源:互联网 发布:python的multiply函数 编辑:程序博客网 时间:2024/05/26 20:22

问题描述

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

输入格式

//输入文件C.in。
第一行输入两个整数n,m,表示城市的大小。
接下来n行,每行m个数,其中第x行第y个数就是ℎ(x,y)。

输出格式

//输出文件C.out。
输出一行一个整数,表示(n+m−1)2×σ2的最小值。

题解

通过将该式子化简可知n*segA^2-(segA)^2
因此定义dp[i][j][k]表示到i j时总和为k的最小n*segA^2

代码

#include<stdio.h>#include<algorithm>#include<cmath>#include<cstring>#include<iostream>#include<queue>#include<cstdio>using namespace std;#define maxn 52#define int long long#define inf 1e9int dp[maxn][maxn][5101];int g[maxn][maxn][5101]; int n,m,maxx;int d[maxn][maxn];main(){    int i,j,k;    scanf("%lld%lld",&n,&m);    for(i=1;i<=n;i++){        for(j=1;j<=m;j++){            scanf("%lld",&d[i][j]);           maxx=max(maxx,d[i][j]);        }    }    for(i=1;i<=n;i++)      for(j=1;j<=m;j++)       for(k=0;k<=maxx*(n+m-1);k++)         dp[i][j][k]=inf;    dp[1][1][d[1][1]]=d[1][1]*d[1][1];    for(i=1;i<=n;i++){        for(j=1;j<=m;j++){            for(k=0;k<=maxx*(n+m-1);k++){                if(dp[i][j][k]==inf) continue;                int dx,dy,t=d[i][j];                dx=i+1;dy=j;                dp[dx][dy][k+d[dx][dy]]=min(dp[dx][dy][k+d[dx][dy]],dp[i][j][k]+d[dx][dy]*d[dx][dy]);                dx=i;dy=j+1;                dp[dx][dy][k+d[dx][dy]]=min(dp[dx][dy][k+d[dx][dy]],dp[i][j][k]+d[dx][dy]*d[dx][dy]);            }//          cout<<dp[i][j][3];        }    }    int minn=1e9;//     for(i=1;i<=maxx*(n+m-1);i++) cout<<dp[n][m][i]<<" ";    for(i=1;i<=maxx*(n+m-1);i++) if(dp[n][m][i]!=inf)minn=min(minn,(n+m-1)*dp[n][m][i]-i*i);    cout<<minn;}
原创粉丝点击