zoukankan      html  css  js  c++  java
  • POJ 1160 Post Office

    题意:有n个村庄,要在其中m个村庄里建邮局,每个村庄去邮局的代价为当前村庄到最近的一个有邮局村庄的路程,问总最小代价是多少。

    解法:dp。dp[i][j]表示在前j个村庄建立i个邮局后的代价,则状态转移方程:dp[i][j] = min{dp[i - 1][k] + f(k + 1, j)},k = i - 1 ... j - 1,f(k + 1, j)表示在k + 1到j这些村庄中放一个邮局的代价,根据贪心的思想,这个邮局应该放在中间的村庄,即第(k + 1 + j) / 2个村庄,暴力的去算f会T,于是用数组sum[i][j]表示只有一个邮局在第i个村庄时,前j个村庄产生的代价,则邮局在第i个村庄时,从j到k村庄的代价为sum[i][k] - sum[i][j - 1]。

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define LL long long
    using namespace std;
    int v[305];
    int dp[35][305];
    int sum[305][305];
    int n, m;
    void init()
    {
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                sum[i][j] = sum[i][j - 1] + abs(v[i] - v[j]);
    }
    int main()
    {
        while(~scanf("%d%d", &n, &m))
        {
            memset(dp, 0, sizeof dp);
            memset(sum, 0, sizeof sum);
            for(int i = 1; i <= n; i++)
            {
                scanf("%d", &v[i]);
            }
            sort(v, v + n);
            init();
            for(int i = 2; i <= n; i++)
            {
                int mid = (i + 1) >> 1;
                dp[1][i] = min(sum[mid][i], sum[mid + 1][i]);
            }
            for(int i = 2; i <= m; i++)
            {
                for(int j = i; j <= n; j++)
                {
                    dp[i][j] = 1000000;
                    for(int k = i - 1; k <= j - 1; k++)
                    {
                        int tmp = 0;
                        if(k + 1 == j) 
                        {
                            dp[i][j] = min(dp[i][j], dp[i - 1][k]);
                            continue;
                        }
                        int mid = (j + k + 1) >> 1;
                        tmp = min(sum[mid][j] - sum[mid][k], sum[mid + 1][j] - sum[mid + 1][k]);
                        dp[i][j] = min(dp[i][j], dp[i - 1][k] + tmp);
                    }
                }
            }
            printf("%d
    ", dp[m][n]);
        }
        return 0;
    }
    

      

  • 相关阅读:
    java的instanceof简单使用
    PHP中return,exit,die的区别
    C#调用Dll文件中方法的简单应用
    C#的托管和非托管的简单理解
    对象造型(引用类型转换)
    面向对象3大特性的简单理解
    css3自定义滚动条背景透明
    console.time方法与console.timeEnd方法
    IE8 input X 去掉文本框的叉叉和密码输入框的眼睛图标
    JavaSript模块规范
  • 原文地址:https://www.cnblogs.com/Apro/p/4857157.html
Copyright © 2011-2022 走看看