• POJ 1160 DP


    题目:
    poj 1160

    题意:

    给你n个村庄和它的坐标,现在要在其中一些村庄建m个邮局,想要村庄到最近的邮局距离之和最近。

    分析:
    这道题。很经典的dp

    dp[i][j]表示建第i个邮局,覆盖到第j个村庄的距离之和。

    问题在于状态方程怎么写?

    dp[i][j]=min(dp[i][j],dp[i-1][k]+dis[k+1][j]) 意思就是建了i个邮局管辖1-j个村庄,或者建i-1个邮局管辖1-k个,而后边的k+1到j个村庄在建第i个。

    其中这个dis[i][j]需要预处理一下。这个dis[i][j]表示 邮局i-j之间只建一个邮局的最优距离。经事实证明,是中点位置。辣么,怎么证明哩?

    可以用反证法,其中还有分成两种情况。
    一. 有奇数个村庄。如果假设不在正中间,比如说往左偏一个见图

    二.有偶数个村庄
    那他没有严格意义上的中点,他中点的左边一个村庄和右边一个村庄是一样的
    (题意&分析From mars_ch)

    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    int a[1000],n,m,d[1000][1000],f[1000][1000];
    int main()
    {
        scanf("%d%d",&m,&n);
        for(int j=1;j<=m;j++)
            scanf("%d",&a[j]);
        memset(f,0x3f,sizeof(f));
        for(int i=1;i<=m;i++)
            for(int j=1;j<=m;j++)
                for(int k=i;k<=j;k++)
                    d[i][j]+=abs(a[(i+j)/2]-a[k]);
        for(int i=0;i<=n;i++)        f[0][i]=0;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=i;k++)
                f[i][j]=min(f[i][j],(f[k-1][j-1]+d[k][i]));
        printf("%d",f[m][n]);
        return 0;
    }
  • 相关阅读:
    Nginx 基本命令
    Nginx配置详细
    MySQL 函数大全
    X-Frame-Options 配置
    Visual Studio提示“无法启动IIS Express Web服务器”的解决方法
    idea java 非web程序打包
    mysql 存储过程
    webstorm 重置所有设置
    vue input 赋值无效
    MySQL 性能优化神器 Explain 使用分析
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532471.html
Copyright © 2020-2023  润新知