您的位置:首页 > 其它

hdu5492 Find a path dp

2015-09-27 18:26 239 查看
//给出n*m的格子
//每一格都有相应的权值,从(1,1)点走到(n,m点)
//(n+m-1)segma(ai-avg)^2(1<=i<=n+m-1)的最小值为多少  avg为所有ai的平均数
//(n+m-1)segma(ai-avg)^2 = (segma((n+m-1)*ai - segma(ai))^2)/(n+m-1)
//(segma((n+m-1)*ai - segma(ai))^2)(1<=i<=(k+1))
//segma((n+m-1)*a[i] - s - a[i+1])^2 = segma((n+m-1)*a[i] -s)^2 - 2* a[i+1]*(n+m-1)*s + a[i+1]^2
//s位segma(a[i]) 
//所以只需要记录s为前面k步的和
//dp[i][j][s] 表示走到位置(i,j)的 (n+m-1)segma(ai-avg)^2的最小值
#include"iostream"
#include"stdio.h"
#include"queue"
#include"stack"
#include"string"
#include"string.h"
#include"stdlib.h"
#include"vector"
#include"map"
#include"ctype.h"
#include"cmath"
#include"algorithm"
#include"set"
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
int dp[35][35][2000];
int dat[35][35];
int n,m;
int main()
{
    ios_base::sync_with_stdio(0);
    int T,cas=0;
    cin>>T;
    while(T--){
        cin>>n>>m;
        memset(dat,0,sizeof(dat));
        memset(dp,INF,sizeof(dp));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>dat[i][j];
            }
        }
        int maxit=dat[1][1];
        int s=dat[1][1];
        dp[1][1][s]=((n+m-2)*dat[1][1])*((n+m-2)*dat[1][1]);
        for(int k=3;k<=n+m;k++){
            for(int i=min(n,k-1);i>=1;i--){
                int j=k-i;
                for(int p=0;p<=maxit;p++){
                    if(dp[i-1][j][p]<INF){
                        int pp=p+dat[i][j];
                        int data=dat[i][j];
                        int sss=dp[i-1][j][p]-2*data*(n+m+1-k)*p+(k-2)*data*data+(data*(n+m-1)-pp)*(data*(n+m-1)-pp);
                        dp[i][j][pp]=min(dp[i][j][pp],sss);
                        maxit=max(pp,maxit);
                    }
                    if(dp[i][j-1][p]<INF){
                        int pp=p+dat[i][j];
                        int data=dat[i][j];
                        int sss=dp[i][j-1][p]-2*data*(n+m+1-k)*p+(k-2)*data*data+(data*(n+m-1)-pp)*(data*(n+m-1)-pp);
                        dp[i][j][pp]=min(dp[i][j][pp],sss);
                        maxit=max(pp,maxit);
                    }
                }
            }
        }
        int ans=INF;
        for(int i=0;i<=maxit;i++){
            ans=min(ans,dp
[m][i]);
        }
        cout<<"Case #"<<++cas<<": ";
        cout<<ans*1.0/(n+m-1)<<endl;
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: