题意:

    有N座环形分布的城市,相邻城市编号相邻,现要建一座酒厂,每个城市对酒的需求不同,每桶酒每千米运费为1元。给定n各城市,所需酒的桶数以及城市间的距离,求酒厂建在哪个城市可使得运费最小。

输入:

    第一行为n,代表城市个数。以下n行分别有两个整数,代表第i个城市每日需酒量和与下一座城市的距离。

输出:

    输出最小运费。

 

    可以使用枚举法,枚举酒厂在各个城市的情况,计算出相应运费得出最小值。也可简化计算,得出建在某一个城市的运费后可以依次推出其他可能的运费。将环形分布的城市根据距离当前酒厂的位置划分为两个区域,ld代表逆时针区域需求量,rd代表顺时针区域需求量,当酒厂从i移动到i+1后,逆时针区域城市到酒厂距离分别增加D,顺时针区域城市则减少D,所以当前运费current = current + D(ld-rd) 。每次移动后,两个区域需要重新划分。

 

#include<iostream>
using namespace std ;
int main(){
    int demand[10000], dist[10000] ;
    int n, i, mid=0, ld=0, rd=0 ;
    int current=0, half, dl=10, s=0, c=0, best ;
    cin >> n ;
    for(i=0; i<n; i++){
        cin >> demand[i] >> dist[i] ;
        c += dist[i] ;
    }
    half = c / 2 ;
    for(i=1; i<n; i++){         //以第一个城市为酒厂所在地
        s += dist[i-1] ;
        if(s<=half){            //小于周长一半,划为顺时针区域
            mid = i ;
            dl = s ;            //标记分界
            current += s*demand[i] ;
            rd += demand[i] ;
        }
        else{                   //否则划为逆时针区域
            current += (c-s)*demand[i] ;
            ld += demand[i] ;
        }
    }
    best = current ;            //假设当前选址为最佳选择
    for(i=1; i<n; i++){         //依次枚举酒厂所在其他城市时的情况
        ld += demand[i-1] ;  //原酒厂所在城市移入逆时针区域
        rd -= demand[i] ;  //将酒厂所在城市移出顺时针区域
        dl -= dist[i-1] ;
        current += (ld-rd)*dist[i-1] ;
        while(dl+dist[mid]<=half){
            dl += dist[mid] ;
            mid = (mid+1)%n ;
            current -= (c-dl-dl)*demand[mid] ;
            ld -= demand[mid] ;
            rd += demand[mid] ;
        }
        if(current<best)
            best = current ;
    }
    cout << best << endl ;
    return 0 ;
}

posted on 2011-08-20 11:11  追逐.  阅读(519)  评论(0编辑  收藏  举报