NOIP2017模拟赛 好线路(dp)

问题描述

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
#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 52
#define int long long
#define inf 1e9
int 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<
        }
    }

    int minn=1e9;
//     for(i=1;i<=maxx*(n+m-1);i++) cout<
    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<

你可能感兴趣的:(NOIP2017模拟赛 好线路(dp))