【动态规划】邮局选址问题

来源:互联网 发布:网络常见诈骗手段 编辑:程序博客网 时间:2024/05/08 03:18

题目:

有一条公路经过V个村庄,每一个村庄都处在整数的坐标点上(这里假设公路为数轴)。规划在这条公路上建立P个邮局,每一个邮局都要建在某个村庄上,要求让不同村庄的人到邮局要走的总路程最小。


分析:

用动态规划的办法,先把输入的村庄排序,然后计算只有一个邮局的情况,然后再根据已有的信息,计算p(p>=2)个邮局时的选址分布,其中p从小到大计算。


class addr_info{public:int dis;int behind;addr_info() :dis(0), behind(0){}};class PostSite{public:vector<vector<int>> postsite;//只有一个邮局时,两个村庄之间的选址位置vector<vector<int>> distance;//两点之间只有一个邮局时,所有村庄要走的距离之和vector<vector<addr_info>> totaldis;//int size;//村庄的数目//假设输入的村庄坐标是大于等于零的整数vector<int> main_function(vector<int> villages, int num_of_postoffices){vector<int> res;if (villages.empty() || num_of_postoffices == 0)return res;size = villages.size();if (num_of_postoffices >= size)return villages;//排序,不可以忘记这一步sort(villages.begin(), villages.end());//初始化postsitepostsite = vector<vector<int>>(size, vector<int>(size,0));for (int l = 0; l < size; ++l){for (int r = l; r < size; ++r){int mid = l + (r - l) / 2;postsite[l][r] = villages[mid];}}//初始化distancedistance = vector<vector<int>>(size, vector<int>(size, 0));for (int l = 0; l < size; ++l){for (int r = l+1; r < size; ++r){int pos = postsite[l][r],sum=0;for (int k = l; k <= r; ++k){if (villages[k] < pos)sum += pos - villages[k];elsesum += villages[k] - pos;}distance[l][r] = sum;}}//计算totaldistotaldis = vector<vector<addr_info>>(size, vector<addr_info>(num_of_postoffices+1));//只有一个邮局的情况for (int i = 0; i < size; ++i){totaldis[i][1].dis = distance[i][size - 1];//totaldis[i][1].behind = i;}//有2个或2个以上邮局的情况for (int p = 2; p <= num_of_postoffices; ++p){for (int i = 0; i <= size - p; ++i){totaldis[i][p].dis = 0x7fffffff;totaldis[i][p].behind = 0;//把[i,j]作为第一个分区for (int j = i; j+1 <= size - (p-1); ++j){int temp = distance[i][j] + totaldis[j+1][p - 1].dis;if (temp < totaldis[i][p].dis){totaldis[i][p].dis = temp;totaldis[i][p].behind = j + 1;//behind记录第二个分区的开始位置}}}}//把结果输出到resoutput(0, num_of_postoffices, res);return res;}void output(int left, int p, vector<int> &res){if (p == 1){res.push_back(postsite[left][size-1]);}else{int right = totaldis[left][p].behind;res.push_back(postsite[left][right - 1]);output(right, p - 1, res);}}};


main函数中这样调用:

PostSite a;//vector<int> v = { 1, 4, 7, 19, 70, 89, 105, 204, 18, 40 };vector<int> v = { 1,2,3,4,5,6,7 };auto r=a.main_function(v, 3);for (auto &i : r)cout << i << "  ";cout << endl;



0 0