全国交通咨询模拟java程序_城市旅游购物交通咨询模拟(最小环floyd法/dp)

本文介绍了一种城市旅游购物交通咨询模拟程序的设计,采用Floyd算法和动态规划(DP)方法,旨在提供最佳的旅游、购物一日游线路。程序允许随机、文件及人工输入数据,能完成最佳线路选择、统计和更新数据,并具备查询和更新功能。通过Floyd法求解最短路径,同时用DP解决所有可能的观光组合,以满足时间、费用和中转次数的最少化要求。
摘要由CSDN通过智能技术生成

题目摘要

城市旅游购物交通咨询模拟

【问题描述】

沈阳城内有若干旅游观光景点和商业区。游客主要以公交车为交通工具出游。假设往返于每个景点和商业区的公交线路不少于6路。旅客希望中转次数最少、时间最短、费用最省。

【设计要求】

设计城市交通咨询模拟程序。

(1)采用图结构、集合等数据结构。

(2)可以随机、文件及人工输入数据。

(3)可以完成旅游、购物一日游的最佳线路。

(4)可以统计数据并满足必要的约束条件。

(5)可以查询和更新数据。

(6)其它完善性或扩展性功能。

思路

此题和URAL - 1004的题目类似,可以按照两种方法,由于是普通的课设,我就按照的是floyd 法来写的,不过需要注意保存路径,以及求最小环的具体算法部分。

Floyd法

#include

#include

#include

#include

#include

using namespace std;

const int INF = 1 << 28;

const int maxn = 100 + 10;

/**/

int n, m;

int ans, num,sum[2],ans1,num1,sum1[2],num2,sum2;

int g[maxn][maxn], dis[maxn][maxn],cost[maxn][maxn],g1[maxn][maxn];

int path[maxn],path1[maxn],pre[maxn][maxn],pre1[maxn][maxn],pre2[maxn][maxn];

int path2[maxn];

void init(int flag,int t) {

FILE *fp;

if(flag) {

if(t==1) fp=fopen("input.txt","r");

if(t==2) fp=fopen("rand.txt","r");

}

n=m=1;

printf("请输入城市景点数和交通线路数量:\n");

if(!flag) {

do {

if(n<=0||m<=0) printf("请重新输入正确的值:\n");

scanf("%d %d", &n,&m);

} while(n<=0||m<=0);

} else fscanf(fp,"%d %d", &n,&m);

for (int i = 1; i <= n; i++)

for (int j = 1; j <= n; j++) {

if (i == j) g1[i][j] = g[i][j] = dis[i][j] = cost[i][j] = 0;

else g1[i][j] = g[i][j] = dis[i][j] = cost[i][j] = INF;

pre[i][j] = pre1[i][j] =pre2[i][j]= i;

}

printf("请输入交通线路(线路预估时间和目的地景点门票价格):\n");

for (int i = 0; i < m; i++) {

int u, v, w, c;

if(!flag) scanf("%d %d %d %d", &u, &v, &w, &c);

else fscanf(fp,"%d %d %d %d", &u, &v, &w, &c);

if (dis[u][v] > w) {

g[u][v] = g[v][u] = dis[u][v] = dis[v][u] = w;

}

if (cost[u][v] > c) {

g1[u][v] = g1[v][u] = cost[u][v] = cost[v][u] = c;

}

}

printf("读取成功!\n");

if(flag) fclose(fp);

}

void randd() {

FILE *fp;

fp=fopen("rand.txt","w");

int a=5,b=20;

int c=(rand() % (b-a+1)) + a;

a=c,b=c*(c-1);

int d=(rand() % (b-a+1)) + a;

fprintf(fp,"%d %d\n",c,d);

for(int i = 0; i

fprintf(fp,"%d %d %d %d\n",(rand() % c) + 1,(rand() % c) + 1,(rand() % (300-10+1)) + 10,(rand() % (300-10+1)) + 10);

fclose(fp);

init(1,2);

}

void floyd(int s,int t) {

sum2=0;

num2=0;

for (int k = 1; k <= n; k++) {

for (int i = 1; i <= n; i++)

for (int j = 1; j <= n; j++) {

if (dis[i][j] > dis[i][k] + dis[k][j]) {

dis[i][j] = dis[i][k] + dis[k][j];

pre2[i][j] = pre2[k][j];

}

}

}

if(dis[s][t]

int p = t;

while (p != s) {

path2[num2++] = p; //记录路径

p = pre2[s][p];

}

path2[num2++] = s;

for(int i=num2-1; i>=0; i--) {

printf("%d ",path2[i]);

}

for (int i = 0; i < num2-1; i++) {

sum2+=g[path2[i]][path2[i+1]];

}

puts("");

printf("总时间为%d 中转次数为:%d\n",sum2,num2);

} else printf("抱歉,没有合适的路线。\n");

}

void floyd1() {

ans = INF;

for (int k = 1; k <= n; k++) {

for (int i = 1; i < k; i++)

for (int j = i + 1; j < k; j++) {

int tmp = dis[i][j] + g[i][k] + g[k][j]; //从k点出发,回到k点

if (tmp < ans) {

ans = tmp;

num = 0;

int p = j;

while (p != i) {

path[num++] = p; //记录路径

p = pre[i][p];

}

path[num++] = i;

path[num++] = k;

}

}

for (int i = 1; i <= n; i++)

for (int j = 1; j <= n; j++) {

if (dis[i][j] > dis[i][k] + dis[k][j]) {

dis[i][j] = dis[i][k] + dis[k][j];

pre[i][j] = pre[k][j];

}

}

}

int p[maxn];

for (int i = 0; i < num; i++) {

p[i]=path[i];

}

sum[0]=sum[1]=0;

for (int i = 0; i < num-1; i++) {

sum[0]+=g[p[i]][p[i+1]];

sum[1]+=g1[p[i]][p[i+1]];

}

sum[0]+=g[p[num-1]][p[0]];

sum[1]+=g1[p[num-1]][p[0]];

}

void floyd2() {

ans1 = INF;

for (int k = 1; k <= n; k++) {

for (int i = 1; i < k; i++)

for (int j = i + 1; j < k; j++) {

int tmp = cost[i][j] + g1[i][k] + g1[k][j]; //从k点出发,回到k点

if (tmp < ans1) {

ans1 = tmp;

num1 = 0;

int p = j;

while (p != i) {

path1[num1++] = p; //记录路径

p = pre1[i][p];

}

path1[num1++] = i;

path1[num1++] = k;

}

}

for (int i = 1; i <= n; i++)

for (int j = 1; j <= n; j++) {

if (cost[i][j] > cost[i][k] + cost[k][j]) {

cost[i][j] = cost[i][k] + cost[k][j];

pre1[i][j] = pre1[k][j];

}

}

}

int p[maxn];

for (int i = 0; i < num1; i++) {

p[i]=path1[i];

}

sum1[0]=sum1[1]=0;

for (int i = 0; i < num1-1; i++) {

sum1[0]+=g[p[i]][p[i+1]];

sum1[1]+=g1[p[i]][p[i+1]];

}

sum1[0]+=g[p[num1-1]][p[0]];

sum1[1]+=g1[p[num1-1]][p[0]];

}

void ConsultMenu() { /*咨询系统菜单*/

printf("\n\n");

printf("************************欢迎进入咨询系统**********************\n");

printf("* 1.咨询最省钱一日游路线 *\n");

printf("* 2.咨询最短时间一日游路线 *\n");

printf("* 3.咨询最快路线 *\n");

printf("* 0.退出 *\n");

printf("**************************************************************\n");

printf("\n\n");

}

void ManageMenu() { /*管理系统菜单*/

printf("\n\n");

printf("************************欢迎进入管理系统**********************\n");

printf("* 1.初始化线路 *\n");

printf("* 2.更新线路 *\n");

printf("* 3.删除线路 *\n");

printf("* 4.查询线路 *\n");

printf("* 5.从文件读取线路 *\n");

printf("* 6.生成随机线路(供测试) *\n");

printf("* 0.退出 *\n");

printf("**************************************************************\n");

printf("\n\n");

}

void MainMenu() { /*主菜单*/

printf("\n\n");

printf("**************欢迎使用城市旅游购物交通咨询模拟系统************\n");

printf("* 1.管理系统 *\n");

printf("* 2.咨询系统 *\n");

printf("* 0.退出 *\n");

printf("**************************************************************\n");

printf("\n\n");

}

void Change() { //更新线路

printf("请输入起始点,更改后的线路预估时间和目的地景点门票价格:\n");

int u, v, w, c;

scanf("%d%d%d%d", &u, &v, &w, &c);

g[u][v] = g[v][u] = dis[u][v] = dis[v][u] = w;

g1[u][v] = g1[v][u] = cost[u][v] = cost[v][u] = c;

printf("更新成功!\n");

}

void Del() { //删除线路

int u,v;

printf("请输入起始点:\n");

scanf("%d%d", &u, &v);

g[u][v] = g[v][u] = dis[u][v] = dis[v][u] = INF;

g1[u][v] = g1[v][u] = cost[u][v] = cost[v][u] = INF;

printf("删除成功!\n");

}

void Find() { //查询某条线路

int u,v;

printf("请输入起始点:\n");

scanf("%d%d", &u, &v);

if((g[u][v]^INF&&g[u][v])||(g[v][u]^INF&&g[v][u])) {

printf("线路信息为:\n");

printf("起始点 终止点 预估时间 价格:\n");

printf("%d %d %d %d :\n", u, v, g[u][v], g1[u][v]);

} else {

printf("Sorry, there is no such route by bus.\n");

}

}

void ManageSystem() {/*管理系统*/

int flag = 1;

while(flag) {

system("cls");

ManageMenu();

int choice=0;

printf("请选择要执行的操作:\n");

scanf("%d",&choice);

switch(choice) {

case 1:

init(0,0);

system("pause") ;

break;

case 2:

Change();

system("pause") ;

break;

case 3:

Del();

system("pause") ;

break;

case 4:

Find();

system("pause") ;

break;

case 5:

init(1,1);

system("pause") ;

break;

case 6:

randd();

system("pause") ;

break;

case 0:

flag = 0;

break;

default:

printf("请输入正确的序号。\n");

system("pause");

}

}

}

void ConsultSystem() { /*咨询系统*/

int flag = 1;

while(flag) {

system("cls");

ConsultMenu();

int choice=0;

printf("请选择要咨询的路线方式:\n");

scanf("%d",&choice);

switch(choice) {

case 1: //咨询最省钱一日游路线

floyd2();

if (ans1 >= INF) printf("No solution.\n");

else {

printf("以下是最省钱一日游路线,您可以选择最近的点开始您的旅游!\n");

for (int i = 0; i < num1; i++) printf("%d ", path1[i]);

printf(" 总时间为%d 总费用为%d 中转次数为:%d\n",sum1[0],sum1[1],num1);

}

system("pause");

break;

case 2:

floyd1();

if (ans >= INF) printf("No solution.\n");

else {

printf("以下是最省时间一日游路线,您可以选择最近的点开始您的旅游!\n");

for (int i = 0; i < num; i++) printf("%d ", path[i]);

printf(" 总时间为%d 总费用为%d 中转次数为:%d\n",sum[0],sum[1],num);

}

system("pause");

break;

case 3:

printf("请输入起点和终点:\n");

int x,y;

do {

if(x<=0||x>m||y<=0||y>n) printf("请重新输入正确的值:\n");

scanf("%d %d", &x,&y);

} while(x<=0||x>m||y<=0||y>n);

floyd(x,y);

system("pause");

break;

case 0:

flag = 0;

break;

default:

printf("请输入正确的序号。\n");

system("pause");

}

}

}

int main() {

srand((int)time(0));

int flag = 1;

while(flag) {

system("cls");

int choice;

MainMenu();

printf("请选择要进入的系统:");

scanf("%d",&choice);

switch(choice) {

case 1:

ManageSystem();

break;

case 2:

ConsultSystem();

break;

case 0:

flag = 0;

break;

default:

printf("请输入正确的序号。\n");

system("pause");

}

}

return 0;

}

/*游客主要以公交车为交通工具出游。

假设往返于每个景点和商业区的公交线路不少于6路。

旅客希望中转次数最少、时间最短、费用最省。*/

状压dp

#include

#include

#include

#define DEBUG printf("Passing [%s] in Line %d\n" , __FUNCTION__ , __LINE__) ;

const int Percent[4] = {6 , 4 , 45 , 55} ;

const int MAX_N = 20 + 5 , MAX_S = (1 << 20) + 10 , ADAY = 12 * 60 , INF = 0x3f3f3f3f ;

struct DATA {

int val , dis , times ;

friend bool operator

friend bool operator >(DATA a , DATA b) {return a.val > b.val ;}

friend DATA operator +(DATA a , DATA b) {return (DATA){a.val + b.val , a.dis + b.dis , a.times + b.times} ;}

}dis[MAX_N][MAX_N] , f[MAX_S][MAX_N] ;

//vertex 0 means home

int T , n , m , cost[MAX_N] , g[MAX_S][MAX_N] ;

void init() {

for (int i = 0 ; i <= n ; ++i)

for (int j = 0 ; j <= n ; ++j) dis[i][j] = (DATA){INF , 0 , 0} ;

}

void print(int S , int a) {

if (!S) return ;

print(S - (1 << a) , g[S][a]) ;

printf("%d " , a) ;

}

int main() {

scanf("%d" , &T) ;

for (; T-- ;) {

scanf("%d %d" , &n , &m) ;

for (int i = 1 ; i <= n ; ++i) scanf("%d" , &cost[i]) ;

init() ;

//Calculate the best path

for (int i = 0 ; i < m ; ++i) {

int x , y , w ;

scanf("%d %d %d" , &x , &y , &w) ;

dis[x][y] = dis[y][x] = (DATA){w * Percent[0] + 1 * Percent[1] , w , 1} ;

}

for (int k = 0 ; k <= n ; ++k)

for (int i = 0 ; i <= n ; ++i)

for (int j = 0 ; j <= n ; ++j)

dis[i][j] = std::min(dis[i][k] + dis[k][j] , dis[i][j]) ;

//Calculate all of the solutions in the best situation

int siz = 1 << (n + 1) ;

for (int S = 0 ; S < 2 ; ++S)

for (int i = 0 ; i <= n ; ++i) f[S][i] = (DATA){-1 , 0 , 0} ;

f[1][0] = (DATA){0 , 0 , 0} ;

for (int S = 2 ; S < siz ; ++S)

for (int i = 0 ; i <= n ; ++i) {

f[S][i] = (DATA){-1 , 0 , 0} ;

if (!(S & (1 << i))) continue ;

int preS = S - (1 << i) ;

if (!preS) continue ;

for (int j = 0 ; j <= n ; ++j) {

if (f[preS][j].val == -1) continue ;

DATA tmp = f[preS][j] + dis[i][j] ;

if (f[S][i] > tmp || f[S][i].val == -1) f[S][i] = tmp , g[S][i] = j ;

}

}

//Assess

int BSet = 0 , BEnd = -1 , BValue = -1 ;

for (int S = 2 ; S < siz ; ++S) {

int BestEnd = -1 ; DATA BestVal = (DATA){-1 , 0 , 0} ;

for (int i = 0 ; i <= n ; ++i) {

if (f[S][i].val == -1) continue ;

DATA tmp = f[S][i] + dis[i][0] ;

if (tmp.dis <= ADAY && (BestVal > tmp || BestVal.val == -1)) BestVal = tmp , BestEnd = i ;

}

if (BestVal.val == -1) continue ;

int TotalCost = 0 , Count = 0 ;

for (int i = 1 ; i <= n ; ++i) if (S & (1 << i)) TotalCost += cost[i] , ++Count ;

int AssessVal = (TotalCost * Percent[2] + BestVal.val * Percent[3]) / Count ;

if (BValue > AssessVal || BValue == -1) BSet = S , BEnd = BestEnd ;

}

print(BSet , BEnd) ; printf("0\n") ;

}

return 0 ;

}

/*

部分变量解释

w[i]的单位为分钟

ADAY 表示一天可游玩的时间,依据w[i]的单位而定,此处为 12 * 60

可以根据需求而修改

其余变量下面会进行详细解释

---

输入格式

T

n m

cost[0 ... n]

u[0...m] v[0...m] w[0...m]

其中

T为数据组数

n为地点 m为交通路线

cost[i]为参观每个地点所需的费用

u[i] v[i] w[i]表示存在一条连接u[i]与v[i]且消耗时间为w[i]的交通路线(双向)

---

思路

**第一部分**

对每条路径而言,存在 w 的时间消耗 以及 1 的中转消耗

对路径进行加权平均计算价值

价值计算方法为

(w * Percent[0] + 1 * Percent[1]) / (Percent[0] + Percent[1])

为了简便运算 在编写过程中将分母除去,仅以分子作为价值

对加权平均后的图跑 Floyd 可得到任意两点 时间和中转最优的方案

如果需要保存路径 可在 Floyd 处添加记录

**第二部分**

设 f[S][i] 表示观光 S 集合内的地点且最后访问的地点为i的最优方案

利用dp可轻易计算出方案,其中 g[S][i] 用于保存dp是从哪个状态转移过来的,便于输出方案

**第三部分**

对于每个观光方案 S ,都找出最优的最后访问节点 BestEnd

即先确定当前方案 S 的最优走法 BestVal ,且保证这个走法的时间是严格限制在ADAY范围内的

(保证一日游的需求,如果需要添加地点游玩时间,可在ADAY的判断条件处稍作修改)

接着对于该方案S,消耗的费用为 TotalCost , 去过的地点为 Count

题目要求 时间、中转、费用最优,以及能够参与更多的景点,同样考虑构造一个函数进行最优化处理

其函数的设计为

(TotalCost * Percent[2] + BestVal.val * Percent[3]) / Count

从而找到最优的方案

*/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值