• hdu 5492(dp)


    题目描述:

    给定一张30*30的图,图上每个点的权值不超过30,让你求

    (N+M−1)∑N+M−1i=1(Ai−Aavg)2的最小值?

    队友将这个式子化成了求方差D[x]=E(x^2)-E(x);

    我猜测是DP,分析一下,这个式子并不具有最优子结构,假设可以经过AB

    到达终点c,选取这两个点的方差的最小值,说明到达这两个点的序列最稳定,

    假设A点是较优点,但是可能会出现,到达A点的最优序列加上c的序列,

    没有到达A的某一个序列加上c的序列优(稳定)

    可以直接化简这个式子得到(A1^2+A2^2+A3^2+...+A[n+m-1]^2*(n+m-1)-(A1+A2+A3+A4+...+A[n+m-1])^2;

    观察一下我们可以维护和和平方和这两项,然后将到达某一个点的所有可能路径

    ,通过和来分类,d[x][y][k]表示到达xy这个点和为k的最小平方和。

     

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    #include <algorithm>
    #include <queue>
    #define maxn 31
    #define  LL long long
    #define inf 0x3f3f3f3f3f3f
    using namespace std;
    int ans;
    int d[maxn][maxn][1800];
    int a[maxn][maxn];
    int dir[2][2]={1,0,0,1};
    int n,m;
    struct node
    {
        int x,y,k;
    };
    void init()
    {
       for(int i=0;i<maxn;i++)
        for(int j=0;j<maxn;j++)
          for(int k=0;k<1800;k++)
            d[i][j][k]=inf;
    }
    void spfa()
    {
        int visit[maxn][maxn];
        memset(visit,0,sizeof(visit));
        queue <node>  que;
        node start;
        start.x=1;  start.y=1;  start.k=a[1][1];
        d[1][1][a[1][1]]=a[1][1]*a[1][1];
        que.push(start);
        visit[1][1]=1;
        while(!que.empty())
        {
            node next,cur=que.front();   que.pop();
            for(int i=0;i<2;i++)
            {
                int x,y,k;
                next.x=x=cur.x+dir[i][0];
                next.y=y=cur.y+dir[i][1];
                next.k=k=cur.k+a[x][y];
                if(next.x>=1 && next.x<=n && next.y>=1 && next.y<=m)
                {
                    int temp=d[cur.x][cur.y][cur.k]+a[x][y]*a[x][y];
                    if(temp<d[x][y][k])
                    {
                       d[x][y][k]=temp;
                        if(visit[x][y]==1)
                            continue;
                        que.push(next);
                        visit[1][1]=1;
                    }
                }
            }
        }
    }
    int main()
    {
        // freopen("test.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int  t;
        scanf("%d",&t);
        int cas = 0;
        while(t --)
        {
            init();
             scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                 scanf("%d",&a[i][j]);
            //work();
            spfa();
            ans=inf;
            for(int k=0;k<=30*59;k++)
            {
               if(d[n][m][k]==inf)
                continue;
               int temp=(n+m-1)*d[n][m][k]-k*k;
               if(temp<=ans && temp>=0)
                    ans=temp;
            }
            printf("Case #%d: %d
    ",++cas,ans);
        }
        return 0;
    }

     

     

  • 相关阅读:
    0414结对 复利
    0619-学习进度条
    测试
    冲刺一总结
    实验四主存空间的分配和回收
    0622-软件工程学期总结
    学术诚信与职业道德有感
    《构建之法》第8、9、10章
    0512 操作系统进程调度实验
    构建之法 第6~7章读后感和对Scrum的理解
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4844847.html
Copyright © 2020-2023  润新知