hdu 1227 简单dp+中位数的性质

来源:互联网 发布:知乎暨南大学临床医学 编辑:程序博客网 时间:2024/05/16 19:08
有一列数X1,X2,X3,...,Xn
f(x)=|X1-x|+|X2-x|+|X3-x|+...+|Xn-x|

当x=数列中位数时,f(x)最小

在做这道题前一定要知道这条结论,然后开始考虑如何进行解题,首先我们定义状态

dp[i][j], i代表现在已经建设了多少个供给站,j代表当前供应到了第几个城市.

那么我们要更新当前情况,必须找到上一个供给站的装态,所以枚举最后一个城市,在i到j之间,然后因为中位数的性质,每次我们建设供给站一定是在中位数的位置.

#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cstdlib>#define MAX 207using namespace std;int n,m;int dp[MAX][MAX];int d[MAX];int c[MAX][MAX];int main ( ){    int cc = 1;    while ( ~scanf ( "%d%d" , &n , &m  ) , n+m )    {        for ( int i = 1 ; i <= n ; i++ ) scanf ( "%d" , &d[i] );        memset ( c, 0 , sizeof ( c ) );        for ( int i = 1 ; i <= n ; i++ )            for ( int j = i; j <= n ; j++ )                for ( int k = i ; k <= j ; k++ )                    c[i][j] += abs ( d[k] - d[(i+j)/2] );        memset ( dp , 0x7f , sizeof ( dp ) );       // cout << dp[0][0] << endl;        dp[0][0] = 0;        for ( int i = 1 ; i <= n ; i++ )            dp[1][i] = c[1][i];        for ( int i = 2 ; i <= m ; i++ )            for ( int j = i ; j <=  n ; j++ )                for ( int k = i-1 ; k < j ; k++ )                    dp[i][j] = min ( dp[i][j] , dp[i-1][k] + c[k+1][j] );        printf ( "Chain %d\n" , cc++ );        printf ( "Total distance sum = %d\n" , dp[m][n] );        puts ( "" );    }}


0 0