2007年高教社杯全国大学生数学建模竞赛题目 B题:乘公交,看奥运
作者:互联网
本题的答题意思就是建立公交系统的网络模型,并按照给出的起点终点拿出相应的解决方案,以及对于方案的评价说明,评价说明也许包括最少的换成次数、最短的总体用时(其中乘车以及换乘都给出了理想化的模型时间)、又或是最小化费,当然人与机器的差别在于人有脑子、有七情六欲,在面临现实的情况时我们也许往往不会单纯追求一种代价的最小,(比如当花费时间很短,但是费用相当之高我们显然也是无法接受的),我们都会综合考虑各种各样的因素,现实中也许我们最后选择的方案单独抽出一样代价(时间、费用或者距离)他都不是最优的但是他确实整体最优的,这就需要一个多方面拟合的估价函数
待补充 时间估价函数、记录估价函数、路径记录函数
/* 注: DEV-C++ 中汉字(包括读取文档的汉字)需用ANSI编码格式 否则读入失败
单一票制的情况全是一元 一定程度上化简了本题难度
没有两个站的编号是相同的
最小花费模型
需要注意的是截取第一个汉字需要s.substr(0,2) 因为 一个汉字占位二
需要完善 最少换乘次数评价函数、
本人很菜,不然谁建模写C++啊
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define Maxn 100005
using namespace std;
string s;
vector<int> v;
struct Node {
int p,value;
bool operator < (const Node &other) const {
return value > other.value;
}
};
struct Edge{
int u,v,w,next;
}e[3000000];
int head[Maxn],tot,flag,dis[Maxn];
bool vis[Maxn];
inline void Add_Edge(int u,int v,int w) {
e[++tot].u = u,e[tot].v = v,e[tot].w = w,e[tot].next = head[u];
head[u] = tot;
}
void Dijkstra(int s) {
priority_queue<Node> q;
memset(dis,0x7f,sizeof(dis));
dis[s] = 0; q.push((Node){s,0});
while(!q.empty()) {
Node u = q.top(); q.pop();
if(vis[u.p]) continue;
vis[u.p] = true;
for(int i=head[u.p]; i; i=e[i].next) {
int v = e[i].v,w = e[i].w;
if(!vis[v] && dis[v] > dis[u.p] + w) {
dis[v] = dis[u.p] + w;
q.push((Node){v,dis[v]});
}
}
}
}
inline int Identifier (int p) {// 站点编号处理函数
int num = 0;
num = (s[p] - '0') * 1000 + (s[p + 1] - '0') * 100 + (s[p + 2] - '0') * 10 + s[p + 3] - '0';
//printf("%d\n",num);
return num;
}
inline int cost(int num) {// 票价处理函数
if(num <= 20) return 1;
else if(num <= 40) return 2;
else return 3;
}
void Alone() {
int len = s.length();
v.clear();
for(int i=0; i<len; i++) {
if(s[i] == 'S') { //每个站点的标识符S
v.push_back(Identifier((i + 1)));
i += 4;
}
else continue;
}
int size = v.size();
for(int i=0; i<size-1; i++) {
for(int j=i+1; j<size; j++)
Add_Edge(v[i],v[j],flag ? cost(j - i) : 1);// 分段计价
}
//cout << "Alone" << endl;
}
void Double() {
int len = s.length();
v.clear();
for(int i=0; i<len; i++) {
if(s[i] == 'S') { //每个站点的标识符S
v.push_back(Identifier((i + 1)));
i += 4;
}
else continue;
}
int size = v.size();
for(int i=0; i<size-1; i++) {
for(int j=i+1; j<size; j++){
Add_Edge(v[i],v[j],flag ? cost(j - i) : 1);
Add_Edge(v[j],v[i],flag ? cost(j - i) : 1);
}
}
//cout << "Double" << endl;
}
void Circle() {
int len = s.length();
v.clear();
for(int i=0; i<len; i++) {
if(s[i] == 'S') { //每个站点的标识符S
v.push_back(Identifier((i + 1)));
i += 4;
}
else continue;
}
int size = v.size();
for(int i=0; i<size-1; i++) {
for(int j=0; j<size; j++){
Add_Edge(v[i],v[j],flag ? cost(min(j - i,size - j + 1)) : 1);
Add_Edge(v[j],v[i],flag ? cost(min(j - i,size - j + 1)) : 1);//双向环
}
}
Add_Edge(v[0],v[size - 1],1);//环上的两个端点 肯定只是坐一站车就到
Add_Edge(v[size - 1],v[0],1);
}
int main() {
freopen("1.txt","r",stdin);
while(1) {
cin >> s;
if(s == "END") break;
cin >> s;
flag = 0; // 0 琛ㄧず鍗曚竴绁ㄤ环 1 琛ㄧず鍒嗘璁′环
if(s == "分段计价。") flag = 1; // 1 代表分段计价
else flag = 0; // 0代表大一票价
//cout << "flag = " << flag << endl;
cin >> s;
if(s.substr(0,2) == "上") {
Alone();
cin >> s;// 有上行必有下行
Alone();
}
else if(s.substr(0,2) == "环") Circle();
else Double();// 双向
}
int s,t;
cout << "===" << endl;
scanf("%d%d",&s,&t);
cout << s << ' ' << t << endl;
Dijkstra(s);
cout << dis[t];// 仅仅是最小花费的估值函数
return 0;
}
标签:int,Add,flag,高教,2007,社杯,Edge,dis,size 来源: https://blog.csdn.net/qq_35776409/article/details/111429132