其他分享
首页 > 其他分享> > 2007年高教社杯全国大学生数学建模竞赛题目 B题:乘公交,看奥运

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