标签:
政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < m。为了提高山区的文化素质,政府又决定从m个村中选择n个村建小学(设 0 < n < = m < 500 )。请根据给定的m、n以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值。
10 2 3 1 3 1 1 1 1 1 3
18
1 #include "bits/stdc++.h" 2 3 using namespace std ; 4 const int INF = 214748364 ; 5 const int maxN = 1e3 ; 6 7 int d [ maxN ] , f [ maxN ][ maxN ] , cost[ maxN ][ maxN ] ; 8 9 int gmin ( int x , int y ) { return x > y ? y : x ; } 10 11 inline int INPUT ( ) { 12 int x = 0 , F = 1 ; char ch = getchar ( ) ; 13 while ( ch < ‘0‘ || ‘9‘ < ch ) { if ( ch == ‘-‘ ) F = -1 ; ch = getchar ( ) ; } 14 while ( ‘0‘ <= ch && ch <= ‘9‘ ) { x = ( x << 1 ) + ( x << 3 ) + ch - ‘0‘ ; ch = getchar ( ) ; } 15 return x * F ; 16 } 17 18 void calc ( int M ) {//计算cost[ i ][ j ] ,即 i 到 j 修建 1 个小学最小距离和。 19 for ( int i=1 ;i<=M ; ++i ) { 20 for ( int j=i+1 ; j<=M ; ++j ){ 21 int Dis = 0 ; 22 int mid = ( i + j ) >> 1 ; 23 for ( int k=i ; k<mid ; ++k )Dis += d[mid] - d[k] ; 24 for ( int k=mid+1 ; k<=j ; ++k )Dis += d[k] - d[mid] ; 25 cost[ i ][ j ] = Dis ; 26 } 27 } 28 } 29 30 void Init_2 ( int N , int M ) { 31 for ( int i=1 ; i<=M ; ++i ) { 32 for ( int j=1 ; j<=N ; ++j ) { 33 if ( j==1 ) f[ i ][ j ] = cost[ 1 ][ i ] ; 34 else f[ i ][ j ] = INF ; 35 } 36 } 37 } 38 void Init_1 ( int M ) { 39 for ( int i=1 ; i<=M; ++i ) 40 for ( int j=i+1 ; j<=M; ++j ) 41 cost[ i ][ j ] = INF ; 42 } 43 44 int main ( ) { 45 int M = INPUT ( ) , N = INPUT ( ) ; 46 for ( int i=2 ; i<=M ; ++i ) 47 d[ i ] = d[ i - 1 ] + INPUT ( ) ; 48 Init_1( M ) ; 49 calc ( M ) ; 50 Init_2 ( N , M ) ; 51 for ( int i=1 ; i<=M ; ++i ) { 52 for ( int j=2 ; j<=N ; ++j ) { 53 for ( int k=0 ; k<i ; ++k ){ 54 f[ i ][ j ] = gmin ( f[ i ][ j ] , f[ k ][ j - 1 ] + cost[ k + 1 ][ i ] ) ; 55 } 56 } 57 } 58 printf ( "%d\n" , f[ M ][ N ] ) ; 59 return 0 ; 60 }
2016-10-20 19:15:13
(完)
标签:
原文地址:http://www.cnblogs.com/shadowland/p/5981602.html