使用C++TR1实现物流配送问题的简单模拟

news/2024/10/17 14:30:25/

   物流配送问题是典型的NP完全问题,寻找求解该问题的高效准确的算法一直以来都是研究热点。我在这里不是讨论解决该问题的具体算法,而是简单介绍一下C++98的一个功能强大扩展--TR1
  TR1Technical Report 1的简称,它原本是标准委员会内部的一个名称。它是在1998年标准委员会提出C++ Standard(就是我们说的"标准C++")之后 委员会拟定的下一个版本的C++ Standard应该具有的功能的一份描述。它仅是一份文档,本身并没有做出具体实现,但其中列出的这些实现很值得我们去了解。关于TR1Effective C++3e)》Item54有比较详细的介绍,这里不多说了。
  支持TR1的开发环境有:
        gcc4.*.*(gcc4.0及以后的版本)
      MSVC2008(vs2008及以后版本)

问题描述:   
    针对一般的分销系统,即系统由分销中心(DC),多个零售商组成,该系统的运营成本主要由运输成本与库存成本构成。分销中心用自己的车辆为各零售商供货,而分销中心由制造商直接供货,假设零售商处的顾客需求是随机的且服从一定的概率分布,不同零售商之间以及同一零售商不同时期之间的需求是独立的。一般DC与零售商均采用周期补货策略,补货时刻为周期末,DC的一个补货周期一般包含多个零售商的补货周期。现考虑只有一个分销中心和30个零售商组成的分销系统,配送货物为单一产品。试就顾客需求服从参数为6Possion分布,销售中心位置为(0,0),30个零售商的位置可在[-200,200]‰[-200,200]的平面上随机产生得到的分销系统的运输、配送策略建立数学模型,并以题目中提供的部分数据为基础,进行数据模拟。

程序实现:

#include <cstdio>#include <iostream>#include <fstream>#include <set>#include <vector>#include <random>using namespace std;using namespace std::tr1;#define PRINT_RES#define PRINT_STEPofstream fout("res.txt");int nTests = 500; // 存放模拟次数const int N = 30; // 零售商const int Q = 18; // 车的载重量typedef double require_t;double x[N+1], y[N+1]; // 零售商的坐标double W[N+1][N+1];        // 带权邻接矩阵require_t q[N+1];      // 零售商处的客户需求inline double squre(double x) {    return x*x; }int main(){random_device rd;   // 随机数引擎mt19937 gen(rd());  // 随机数算法uniform_int<double> uniform(-200, 200); // 均匀分布随机数发生器poisson_distribution<double> poisson(6.0); // 泊松分布随机数发生器x[0] = y[0] = 0.0;double res=0;cout<<"请输入试验次数:";cin >> nTests; // 输入模拟次数for(int t=1; t<=nTests; t++) {// 生成随机数:int rc1 = 1, rc2 = 1;;set<double> sreq;set< pair<double, double> > pset;while( rc1 <= N || rc2 <= N ) {// 零售商位置 服从均匀分布x[rc1] = uniform(gen);y[rc1] = uniform(gen);if( !(x[rc1] == 0.0 && y[rc1] ==0.0) ) {pset.insert( pair<double, double>( x[rc1], y[rc1] ) );rc1++;}// 客户需求 服从泊松分布q[rc2] = poisson(gen); if( q[rc2] > 0.0 ) {sreq.insert( q[rc2] );rc2++;}}       // 更新邻接矩阵:for(int i=0; i<=N; i++) {for(int j=0; j<=N; j++)  {W[i][j] = sqrt( squre(x[i]-x[j]) + squre(y[i]-y[j]) );}}set<int> V;for(int i=1; i<=N; i++) V.insert(i);/***************************************************************************贪婪算法(greedy algorithm)时间复杂度:O(n^2*log2(n))Step1: 令S={},u=0, k=1;Step2: 令R(k)={u},Qt=Q;Step3: 构建集合AR(u)={e| e∈A(u)且e∈S,且q(e) < Qt };Step4: 如果AR(u)≠{},则从AR(u)中找到到u的权最小的x,更新R(k),S,Qt,u:R(k)=R(k)∪{x},S=S∪{x},Qt=Qt-q(x),u=x;跳转到(3);否则,继续(5);Step5: 如果S≠V,则k=k+1,u=0转到(2);否则,结束;****************************************************************************/// 1.   令S={},u=0, k=1;set<int> S;int u=0, k=1;       vector<int> R[N+1];           while(1) {// 2.令R(k)={u},Qt=Q;R[k] = vector<int>(1, u); double Qt = Q;      while(1) {// 3.构建集合AR(u)={e| e∈A(u)且e∈S,且q(e) < Qt }set<int> AR;for(int e=1; e<=N; e++) {if( W[u][e]!=0 && q[e]<Qt && S.count(e)==0 )AR.insert( e );}// 4.从AR(u)中找到到u的权最小的x,更新R(k),S,Qt,uif( AR.size() ) {double minw = 0;int minx=0;set<int>::iterator it=AR.begin();for( ;it != AR.end(); it++ ) {if( q[*it]/W[u][*it] > minw ) {minx = *it; }}                   R[k].push_back( minx );S.insert( minx );Qt -= q[ minx ];u = minx;continue;}else break;}// 5.如果S≠V,则k=k+1,u=0转到(2);否则,结束;if( S != V ) {if( V.size() - S.size() == 1 ) {R[k+1] = vector<int>(2, 0);R[k+1][1] = *V.begin();break;}if( R[k].size()>1 ) k++; u=0;continue;}else break;}// 计算本次模拟的 运营成本:double C=0;for(int i=1; i<=N; i++) {if( R[i].size() )  {vector<int>::iterator it=R[i].begin();for( ; it+1!=R[i].end(); it++) {C += W[*it][*(it+1)];}C += W[*it][0];}}// 打印各次配送的路线:printf("\n第%d次模拟...\n", t);for(int i=0; i<=N; i++) {if( R[i].size() ) {printf("第%d趟发货:\t", i);//int j=0, sz = R[i].size();vector<int>::iterator it=R[i].begin();for( ; it!=R[i].end(); it++) {printf("%d\t", *it );// printf("(%d,%d)\t", *it, *(it+1) );} // printf("(%d,%d)\t", *it, 0 );printf("\n");}}printf("运输成本: %g\n", C);fout << C << "\n";res += C;}printf("\n模拟次数:%d\n平均运输成本:%g\n", nTests, res/nTests );return 0;}

 注:以上代码只在vc2008中编译通过,在gcc中编译可能会出现问题(在我的gcc上没有编译成功,好像是gcc实现版的TR1所在的头文件不太一样)。

    这里只用到了TR1的随机数生成工具,它大大超越了rand(),它除了提供正态分布以外,还提供了正态分布、泊松分布、伯努利分布等概率分布,而且使用起来也相当简单。

这里是关于TR1的一份清单:

EC++
Page
Effective C++, Third Edition
Name
TR1 NameProposal
Document
265Smart PointersSmart Pointersn1450
265tr1::functionPolymorphic Function Wrappersn1402
266tr1::bindFunction Object Bindersn1455
266Hash TablesUnordered Associative Containersn1456
266Regular ExpressionsRegular Expressionsn1429
266TuplesTuple Typesn1403 (PDF)
267tr1::arrayFixed Size Arrayn1479
267tr1::mem_fnFunction Template mem_fnn1432
267tr1::reference_wrapperReference Wrappersn1453
267Random Number GenerationRandom Number Generationn1452
267Mathematical Special FunctionsMathematical Special Functionsn1422
267C99 Compatibility ExtensionsC Compatibilityn1568
267Type TraitsMetaprogramming and Type Traitsn1424
267tr1::result_ofFunction Return Typesn1454


关于TR1的描述的原始链接:http://www.aristeia.com/EC3E/TR1_info.html

 最新的C++标准已在去年发布,即C++11.

关于C++11的一份清单(包括C++全部内容):

C++参考
C++98,C++03,C++11

语言

预处理器
关键字
运算符优先级
转义序列
ASCII表
基本类型

概念

实用工具库

类型的支持
动态内存管理
错误处理
程序实用工具
日期和时间
bitset
函数对象
pair  −   tuple (C++11)

字符串库

basic_string
NULL结尾的字节串
NULL结尾的多字节字符串
NULL结尾的宽字符串

容器库

array (C++11)  −  vector  −  deque
list  −  forward_list (C++11)
set  −  multiset
map  −  multimap
unordered_set (C++11)
unordered_multiset (C++11)
unordered_map (C++11)
unordered_multimap (C++11)
stack  −  queue  −  priority_queue

算法库

迭代器库

数值算法库

常见的数学函数
复数
伪随机数生成

输入/输出库

basic_streambuf
basic_filebuf
basic_stringbuf
ios_base
basic_ios
basic_istream
basic_ostream
basic_iostream
basic_ifstream
basic_ofstream
basic_fstream
basic_istringstream
basic_ostringstream
basic_stringstream
I / O操纵
C-风格的I / O

本地化库

正则表达式库 (C++11)

原子操作库 (C++11)

线程的支持库 (C++11)

关于每个内容的详细说明http://www.cplusplus.com/上也有不错的说明(两个网站的内容差不多).原始链接:http://zh.cppreference.com/w/%E9%A6%96%E9%A1%B5

  但目前,支持C++11的编译器并不多,只有:

       gcc 4.7.*

    VC2012 

   C++11有更多更强大、更有趣的内容供我们使用,我们要做的就是去熟悉。


转载于:https://www.cnblogs.com/xusw/archive/2012/12/06/5205869.html


http://www.ppmy.cn/news/798642.html

相关文章

JZOJ5959【NOIP2018模拟11.8A组】铁路运输

Description Input Output Data Constraint 题意&#xff1a;给出一个边权为1的无向图&#xff0c;q次操作&#xff0c;将一条边的边权变为2&#xff0c;每次操作后询问有多少个点的通往1的最短路比所有操作前的最短路小。 无向图上的边权修改问题不好做&#xff0c;我们可以考…

专利检索及分析模拟登陆(python)

登陆程序&#xff1a;#!/usr/bin/env python # -*- coding: UTF-8 -*-import requests import time import base64codeurl http://www.pss-system.gov.cn/sipopublicsearch/portal/login-showPic.shtmlproxies {http: http://140.205.222.3:80,https: http://117.127.0.196:8…

Ubuntu: scp命令使用及Permission denied错误解决方案

scp命令介绍 scp 命令用于 Linux 之间复制文件和目录。scp 是 secure copy 的缩写, scp 是 Ubuntu 系统下基于 ssh 登陆进行安全的远程文件拷贝命令。 scp local_file remote_usernameremote_ip:remote_folder scp /Users/X.pem root192.168.1.247:/usr/local/ssl Permission…

【Java|基础篇】面向对象三大特性之继承(上)

文章目录 1. 前言2. 问题提出3. 什么是继承4. 继承的特点 1. 前言 继承是面向对象三大特性之一. Java的继承也是很复杂. 本篇文章先帮助大家理解继承的概念 2. 问题提出 先来看这两个类: Student类: public class Student {private String name;private int age;private S…

单反相机的照片不见了如何恢复

转眼又到了春暖花开的日子了&#xff0c;而且春夏季节&#xff0c;我们的节假日又多&#xff0c;正好出去踏春。我和女友都攒了年假没有修&#xff0c;又接了一个法定假日&#xff0c;打算去云南走一趟。结果旅途中还发生了一键关于照片恢复的插曲。 我们两个都是旅游发烧友&am…

索尼相机里的照片要怎么恢复

索尼相机是去日本的时候购买的&#xff0c;都说日本的数码产品好&#xff0c;也不知道我的运气是好还是不好&#xff0c;虽然有机会去日本&#xff0c;但是却没有大钱去购买过于高端的产品&#xff0c;刚好缺一个数码相机&#xff0c;于是就购置了一个。日本的数码相机牌子不少…

sony相机照片恢复|Mac电脑sony相机照片误删了怎么恢复?

索尼照相机是索尼公司的优质产品之一&#xff0c;索尼照相机走的是高端时尚前卫路线&#xff0c;CCD技术先进&#xff0c;便携中的高像素&#xff0c;防抖&#xff0c;自动捕捉头像&#xff0c;而且索尼照相机还支持笑脸快门&#xff0c;可以捕捉精彩的一瞬间。因此受到了广大摄…

索尼相机卡照片误删丢失恢复图文教程

相机卡很多摄影爱好者都会多备用几个&#xff0c;也是相机拍照录视频必不可少的东西&#xff0c;那么大家有没有遇到过相机卡照片不小心删除或者在电脑上意外格式化呢&#xff1f;小编就遇到过&#xff0c;然后还是很快的借助工具恢复回来了&#xff0c;那么现在小编就把如何使…