Find a path
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
Frog fell into a maze. This maze is a rectangle containing
N
rows and
Frog is a perfectionist, so he’d like to find the most beautiful path. He defines the beauty of a path in the following way. Let’s denote the magic values along a path from (1, 1) to (n, m) as
A1,A2,…AN+M−1
, and
Aavg
is the average value of all
Ai
. The beauty of the path is
(N+M–1)
multiplies the variance of the values:
(N+M−1)∑N+M−1i=1(Ai−Aavg)2
In Frog’s opinion, the smaller, the better. A path with smaller beauty value is more beautiful. He asks you to help him find the most beautiful path.
Input
The first line of input contains a number
T
indicating the number of test cases (
Each test case starts with a line containing two integers
N
and
Output
For each test case, output a single line consisting of “Case #X: Y”.
X
is the test case number starting from 1.
Sample Input
1
2 2
1 2
3 4
Sample Output
Case #1: 14
分析:
题意是:有一个N*M的网格,每个格子都有值,问从(1,1)到(N,M)
(N+M−1)∑N+M−1i=1(Ai−Aavg)2
的最小值。
设:dp[i][j][k]表示到(i,j)且和为k的
∑ni=1(Ai)2
的最小值,所以递推公式为:
dp[i][j][k]=min(dp[i-1][j][k-m[i][j]]+m[i][j]*m[i][j],dp[i][j-1][k-m[i][j]]+m[i][j]*m[i][j],dp[i][j][k]);
最后d[N][M][i]为到(N,M)的所有的可能的情况,在里面找最小的(N+M-1)*dp[N][M][i]-i*i即可。
(感觉是动态规划+背包的思想)
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include<limits.h>
using namespace std;
const int maxn = 40;
long long dp[maxn][maxn][1900];
int m[maxn][maxn];
long long min(long long a,long long b)
{
return a<b?a:b;
}
int main()
{
int T,N,M;
int cas=0;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++)
{
for(int j=1;j<=M;j++)
{
scanf("%d",&m[i][j]);
}
}
for(int i=0;i<=N;i++)
{
for(int j=0;j<=M;j++)
{
for(int k=0;k<=1800;k++)
{
dp[i][j][k]=LLONG_MAX;
}
}
}
dp[1][1][m[1][1]]=m[1][1]*m[1][1];
for(int i=1;i<=N;i++)
{
for(int j=1;j<=M;j++)
{
for(int k=m[i][j];k<=1800;k++)
{
if(dp[i-1][j][k-m[i][j]]<LLONG_MAX)
dp[i][j][k]=min(dp[i-1][j][k-m[i][j]]+m[i][j]*m[i][j],dp[i][j][k]);
if(dp[i][j-1][k-m[i][j]]<LLONG_MAX)
dp[i][j][k]=min(dp[i][j-1][k-m[i][j]]+m[i][j]*m[i][j],dp[i][j][k]);
}
}
}
long long ans = LLONG_MAX;
for(int i=0;i<=1800;i++)
{
if(dp[N][M][i]!=LLONG_MAX)
ans = min((N+M-1)*dp[N][M][i]-i*i,ans);
}
printf("Case #%d: %I64d\n",++cas,ans);
}
return 0;
}