zoukankan      html  css  js  c++  java
  • 邮局

    Description

    一些村庄建在一条笔直的高速公路边上。我们用一条坐标轴来描述这条高速公路,每一个村庄的坐标都是整数,没有两个村庄坐标相同。两个村庄间的距离,定义为它们的坐标值差的绝对值。我们需要在一些村庄建立邮局――当然,并不是每一个村庄都必须建立邮局,邮局必须被建在村庄里,因此它的坐标和它所在村庄坐标相同。每个村庄便用离它最近的那个邮局,建立这些邮局的原则是:所有村庄到各自所使用的邮局的距离总和最小。

    你的任务是编写一个程序,在给写了每个村庄的坐标和将要建立的邮局数之后,按照上述原则,合理地选择这些邮局的位置。

    Analysis

    对于前i个村庄,j个邮局而言,不确定的因素为第j个邮局为哪几个村庄提供邮件,一定是为k~i(k<=i)一连串的村庄。为使距离总和最小,必须要放置于k-i的中位数。则枚举k,函数treat(k,i)。

    动规可行性判断:

    • 最优子结构:(k,j-1)最优才能使(i,j)最优
    • 无后效性:处理完一段村庄后不会影响之后邮局的放置。
    dp[i][j]=dp[k][j-1]+treat(k+1,i)
    

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int n,m,p[301],dp[301][301];
    
    int treat(int b,int e)
    {
    	int mid=(b+e)/2,res=0;
    	if((b+e)&1)
    	{
    		for(int i=b;i<mid;i++)
    			res+=p[mid]-p[i];
    		for(int i=mid+2;i<=e;i++)
    			res+=p[i]-p[mid];
    		res+=p[mid+1]-p[mid];
    	}
    	else 
    	{
    		for(int i=b;i<mid;i++)
    			res+=p[mid]-p[i];
    		for(int i=mid+1;i<=e;i++)
    			res+=p[i]-p[mid];
    	}
    	return res;
    }
    
    int main()
    {
    	freopen("test.in","r",stdin);
    	freopen("test.out","w",stdout);
    	cin>>n>>m;
    	for(int i=1;i<=n;i++)
    		cin>>p[i];
    	memset(dp,0x3f,sizeof(dp));
    	dp[0][0]=0;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			for(int k=1;k<=i;k++)
    			dp[i][j]=min(dp[i][j],dp[i-k][j-1]+treat(i-k+1,i));
    	cout<<dp[n][m]<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    poj 1088 滑雪
    位运算与bitset
    hdu 4607 Park Visit
    树的直径
    codeforces 495D Sonya and Matrix
    German Collegiate Programming Contest 2015(第三场)
    BAPC 2014 Preliminary(第一场)
    Benelux Algorithm Programming Contest 2014 Final(第二场)
    E. Reachability from the Capital(tarjan+dfs)
    poj2104 K-th Number(划分树)
  • 原文地址:https://www.cnblogs.com/qswx/p/9492439.html
Copyright © 2011-2022 走看看