• 快餐店


    题目描述:

    排成一条直线的公路上有N个加油站,为了方便加油站的员工吃饭,需要在这N个加油站点位置选K个开设快餐店。那么问题来了,怎样选取能使得每个加油站都可以就近吃饭。所谓的就近吃饭,就是每个加油站的人员会去最近的快餐店吃饭,需要走两个加油站之间的距离。我们的目标是让每个加油站到最近快餐店的距离之和最小(具体可以看样例解释)。

    输入:

    输入N, K
    然后接下来N行,每行输入一个整数ai,表示加油站的位置(这个位置的值是递增的)

    输出:

    输出最小的距离之和,格式见样例输出。

    样例输入:

    6 3
    5
    6
    12
    19
    20
    27

    样例输出:

    Total distance sum = 8

    分段时,每段的数量有限制的题型,使用分段DP的方法。可以将问题划分子问题为区间[1,i]划分成j段,最少需要多少代价,那么我们可以用数组dp[i][j]表示前i个快餐店分成j段的最小代价,转移方程为:
    dp[i][len]=min(dp[i][len],dp[j][len-1]+cost[j+1][i]);
    在这之前,我们需要预处理出[i,j]这一段需要的代价,用cost[i][j]表示。这段区间,快餐店应该设在中位数所在的站点,会使得区间[i,j]一段的代价最小。
    综上,我们就可以用分段DP的方式了(哈哈哈哈哈哈哈哈哈哈哈哈哈哈啊哈哈):

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,a[205],dp[205][35],cost[205][205];
    int zxy()
    {
    for(int i=1;i<=n;i++)
    {
        dp[i][1]=cost[1][i];
        for(int j=2;j<=m;j++)dp[i][j]=100000000;
    }
    for(int len=2;len<=m;len++)
    for(int i=len;i<=n;i++)
    for(int j=len-1;j<=i-1;j++)
    {
        dp[i][len]=min(dp[i][len],dp[j][len-1]+cost[j+1][i]);
    }
    return dp[n][m];
    }
    int main()
    {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    for(int j=i;j<=n;j++)
    {
        int mid=(i+j)>>1;
        cost[i][j]=0;
        for(int k=i;k<=j;k++)
        cost[i][j]+=abs(a[mid]-a[k]);
    }
    int res=zxy();
    printf("Total distance sum = %d
    ",res);
    return 0;
    } 
  • 相关阅读:
    shell中的for循环
    tty相关
    udev规则
    find中perm参数
    日志级别的选择:Debug、Info、Warn、Error还是Fatal
    云计算、云存储、大数据
    JSON数据解析(python3.4)
    38、友盟统计
    37、iamgeview 图层叠加
    36、imageview的坑
  • 原文地址:https://www.cnblogs.com/Zhoier-Zxy/p/8067389.html
Copyright © 2020-2023  润新知