1131. Subway Map 引用

参考了这位大神的思路。http://blog.youkuaiyun.com/bendaai/article/details/63253277

注释了下代码,方便看了。PS:这个题想了好久好久好久好久。。感觉自己太弱了。

再处理地铁地图的时候最开始用一个数组标记地铁线的,然后标记出换乘车站,把问题复杂化了。

我们建一个这样的图,以地铁站的号为标记,这个节点里面存储相连的车站和线号。看下面这个图。原图引用自:https://www.patest.cn/contests/pat-a-practise/1131


这样有什么好处呢?

这样可以很容易的处理线号,不至于说像我之前那样区别处理要分很多情况。然后用DFS+回溯的方法,遍历图。

#include <iostream>
#include <vector>
#include <cstring>

#define MAX 10010

using namespace std;

struct Station {//车站节点 包括车站号和线号
	int No;
	int LineNo;
	Station(int no, int lineno) {
		No = no;
		LineNo = lineno;
	}
};

struct MapNode { //地铁网线图 包含相连车站的车站号和线号
	vector <Station> Link;
};

struct Segment { //乘车区间
	int LineNo;
	int Start, End;
	Segment(int lineno, int st, int ed) {
		LineNo = lineno;
		Start = st;
		End = ed;
	}
};

struct Ans {//最后结果
	vector <Segment> list;//所有乘车区间
	int len;//所需长度
	bool operator<(const Ans a2) const {
		if (len != a2.len)
			return len < a2.len;
		else
			return list.size() < a2.list.size();
	}
};

MapNode SubMap[MAX];
int n, m, k;
bool isVis[MAX];


Ans ThisAns;
Ans FinalAns;

void DFS(int u, int ed) { //u当前访问节点
	
	if (u == ed) {//已经遍历完成
		if (ThisAns < FinalAns)//当前结果更优
			FinalAns = ThisAns;
	}

	//当前结果已经不如目前最优结果 不再继续遍历
	if (FinalAns < ThisAns) 
		return;


	for (int i = 0; i < SubMap[u].Link.size(); i++) { //访问u的相连站
		int v = SubMap[u].Link[i].No;
		if (!isVis[v]) {//v没有访问过			
			Ans TempAns = ThisAns;//保存当前结果 方便后面回溯

			ThisAns.len++;
			if (SubMap[u].Link[i].LineNo != ThisAns.list.back().LineNo)
				ThisAns.list.push_back(Segment(SubMap[u].Link[i].LineNo, u, v));
			else
				ThisAns.list.back().End = v;

			isVis[v] = true;
			DFS(v, ed);

			//回溯
			isVis[v] = false;
			ThisAns = TempAns;
		}
	}
	
}

void ParamInit() {//初始化参数
	memset(isVis, false, sizeof(isVis));
	ThisAns.list.clear();
	ThisAns.len = 0;
	ThisAns.list.push_back(Segment(-1, -1, -1));//添加一个初始节点 方便后面的判断
	FinalAns.list.clear();
	FinalAns.len = MAX;
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> m;
		int PreNo, StaNo;
		cin >> PreNo;
		for (int j = 1; j < m; j++) {
			cin >> StaNo;
			SubMap[PreNo].Link.push_back(Station(StaNo, i));
			SubMap[StaNo].Link.push_back(Station(PreNo, i));
			PreNo = StaNo;
		}
	}

	cin >> k;
	for (int i = 0; i < k; i++) {
		ParamInit();//初始化参数
		int st, ed;
		cin >> st >> ed;
		DFS(st, ed);
		cout << FinalAns.len << endl;
		for (int i = 1; i < FinalAns.list.size(); i++) {
			printf("Take Line#%d from %04d to %04d.\n", FinalAns.list[i].LineNo, FinalAns.list[i].Start, FinalAns.list[i].End);
		}
	}

	return 0;
}


[plugin:vite:import-analysis] Failed to resolve import "@dcloudio/uni-ui/lib/uni-loading/uni-loading.vue" from "E:/SmCity/pages/Subway/Subway.vue". Does the file exist? 19:57:32.237 at pages/Subway/Subway.vue:131:9 19:57:32.240 1 | import __easycom_0 from '@dcloudio/uni-ui/lib/uni-search-bar/uni-search-bar.vue';import { resolveDynamicComponent as __resolveDynamicComponent } from 'vue';import { resolveEasycom } from '@dcloudio/uni-app';import '@dcloudio/uni-components/style/text.css';import { Text as __syscom_1 } from '@dcloudio/uni-h5';import __easycom_2 from '@dcloudio/uni-ui/lib/uni-icons/uni-icons.vue';import '@dcloudio/uni-components/style/view.css';import { View as __syscom_3 } from '@dcloudio/uni-h5';import '@dcloudio/uni-components/style/scroll-view.css';import '@dcloudio/uni-components/style/refresher.css';import { ScrollView as __syscom_4 } from '@dcloudio/uni-h5';import __easycom_5 from '@dcloudio/uni-ui/lib/uni-popup/uni-popup.vue';import __easycom_6 from 'E:/SmCity/components/ScBuysList/ScBuysList.vue';import '@dcloudio/uni-components/style/input.css';import { Input as __syscom_7 } from '@dcloudio/uni-h5';import '@dcloudio/uni-components/style/button.css';import { Button as __syscom_8 } from '@dcloudio/uni-h5';import __easycom_9 from '@dcloudio/uni-ui/lib/uni-loading/uni-loading.vue';import '@dcloudio/uni-components/style/radio.css';import { Radio as __syscom_10 } from '@dcloudio/uni-h5';import '@dcloudio/uni-components/style/label.css';import { Label as __syscom_11 } from '@dcloudio/uni-h5';import '@dcloudio/uni-components/style/radio-group.css';import { RadioGroup as __syscom_12 } from '@dcloudio/uni-h5';import { 19:57:32.240 | ^ 19:57:32.240 2 | computed, 19:57:32.240 3 | ref, 19:57:32.296 [Vue warn]: Unhandled error during execution of async component loader \n at <AsyncComponentWrapper>\nat <PageBody>\nat <Page>\nat <Anonymous>\nat <KeepAlive>\nat <RouterView>\nat <Layout>\nat <App> 19:57:32.298 ‍[⁠TypeError⁠]‍ {message: "Failed to fetch dynamically imported module: http:…host:5173/pages/Subway/Subway.vue?t=1750161451638"} <template> <view class="bus-wrap"> <!-- 搜索栏 --> <uni-search-bar placeholder="搜索站点" ref="searchbar" @confirm="search"></uni-search-bar> <uni-popup ref="popup" type="bottom" background-color="#fff"> <view class="popup-content"> <view class="popup-header"> <text class="popup-title">搜索结果</text> <uni-icons type="closeempty" size="24" color="#999" @click="closePopup"></uni-icons> </view> <scroll-view scroll-y class="result-list"> <view v-if="searchData.length === 0" class="empty-result"> <text>未找到相关站点</text> </view> <view v-for="(result, index) in searchData" :key="index" class="result-item"> <text class="result-name">{{ result.name }}</text> <text class="result-line">可乘坐: {{ result.linesId }}号线</text> </view> </scroll-view> </view> </uni-popup> <!-- 原有站点信息区域--> <view class="bus-stops" style="height: 600rpx; overflow-y: scroll;"> <view v-for="(stop, index) in busStops" :key="stop.stepsId" class="stop-item" :style="{ backgroundColor: index % 2 === 0 ? '#52a5f8' : '#0066FF' }"> <text class="stop-name">{{ stop.name }}</text> <text class="stop-sequence">乘坐: {{ stop.linesId }}号线</text> </view> </view> <!-- 原有站点路线 --> <ScBuysList>> <template #itemSlot="item"> <view class="info" @click="gotoDetail(item.id)"> <text class="title">{{ item.name }}</text> <text class="details">起点: {{ item.first }}, 终点: {{ item.end }}</text> </view> <view class="price">价格: ¥{{ item.price }}</view> </template> </ScBuysList> <!-- 新增订单创建区域 --> <view class="order-section"> <view class="section-title"> <text>创建巴士订单</text> </view> <view class="form-item"> <text class="label">起点</text> <input class="input" v-model="orderForm.start" placeholder="请输入起点" /> </view> <view class="form-item"> <text class="label">终点</text> <input class="input" v-model="orderForm.end" placeholder="请输入终点" /> </view> <view class="form-item"> <text class="label">路线</text> <input class="input" v-model="orderForm.path" placeholder="请输入路线" /> </view> <view class="form-item"> <text class="label">价格</text> <input class="input" v-model="orderForm.price" placeholder="请输入价格" type="number" /> </view> <button class="submit-btn" @click="createOrder">提交订单</button> </view> <!-- 订单列表区域 --> <view class="order-list-section"> <view class="section-title"> <text>我的订单</text> <button class="refresh-btn" @click="fetchOrders"> <uni-icons type="refresh" size="16" color="#4a90e2"></uni-icons> <text>刷新</text> </button> </view> <view v-if="orderLoading" class="loading"> <uni-loading type="circle" color="#4a90e2"></uni-loading> </view> <view v-else-if="orders.length === 0" class="empty"> <text>暂无订单记录</text> </view> <view v-else class="orders-container"> <view v-for="order in orders" :key="order.id" class="order-item"> <view class="order-header"> <text class="order-number">订单号: {{ order.orderNum }}</text> <text class="order-status" :class="getStatusClass(order.status)"> {{ getStatusText(order.status) }} </text> </view> <view class="order-content"> <text class="route">{{ order.path }}: {{ order.start }} → {{ order.end }}</text> <text class="price">¥{{ order.price }}</text> </view> <view v-if="order.status === 0" class="order-actions"> <button class="pay-btn" @click="showPayPopup(order)">支付</button> <button class="cancel-btn" @click="cancelOrder(order.id)">取消</button> </view> </view> </view> </view> <!-- 支付弹窗 --> <uni-popup ref="payPopup" type="bottom" background-color="#fff"> <view class="pay-popup"> <view class="popup-header"> <text class="popup-title">订单支付</text> <uni-icons type="closeempty" size="24" color="#999" @click="closePayPopup"></uni-icons> </view> <view class="pay-content"> <text class="order-number">订单号: {{ currentOrder.orderNum }}</text> <text class="pay-amount">支付金额: ¥{{ currentOrder.price }}</text> <radio-group class="payment-methods" @change="handlePaymentMethodChange"> <label class="payment-method"> <radio value="wechat" checked /> <text>微信支付</text> </label> <label class="payment-method"> <radio value="alipay" /> <text>支付宝</text> </label> </radio-group> <button class="confirm-pay-btn" @click="payOrder">确认支付</button> </view> </view> </uni-popup> </view> </template> <script setup> import { computed, ref, onMounted } from 'vue'; import { ip, getHttp } from '../../utils/http.js'; import { onLoad } from '@dcloudio/uni-app' // 站点信息相关数据 const busStops = ref([]); const linesId = ref(); const stepsId = ref(); const searchbar = ref(null) const popup = ref(null) const searchData = ref([]) //订单 const busOrder = ref() // 关闭弹窗 const closePopup = () => { popup.value.close() } // 搜索事件 const search = (e) => { searchData.value = [] console.log('搜索关键字: ' + e.value); const keyword = e.value.trim(); // 去除前后空格 for (let i = 0; i < busStops.value.length; i++) { const stop = busStops.value[i]; if (stop.name.includes(keyword)) { searchData.value.push({ linesId: stop.linesId, name: stop.name }); } } console.log('搜索结果:', searchData.value); popup.value.open() searchbar.value.cancel() } // 获取站点信息 async function getBusStops() { const result = await getHttp({ url: '/prod-api/api/bus/stop/list', data: { stepsId:stepsId.value, name:name.value, linesId: linesId.value } }); busStops.value = result.data.rows; console.log('站点信息:', busStops.value); } // 在组件挂载时调用获取站点信息的函数 onMounted(() => { getBusStops(); }); // 跳转至路线详情 const gotoDetail = (id) => { uni.navigateTo({ url: '/pages/Subway/BuysDetail?id=' + id }); } // 订单相关数据 const orderForm = ref({ start: '', end: '', path: '', price: '', status: 0 }); const orders = ref([]); const orderLoading = ref(false); const payPopup = ref(null); const currentOrder = ref({}); const paymentType = ref('wechat'); // 创建订单 const createOrder = async () => { if (!orderForm.value.start || !orderForm.value.end || !orderForm.value.path || !orderForm.value.price) { return uni.showToast({ title: '请填写完整订单信息', icon: 'none' }); } try { const result = await getHttp({ url: '/prod-api/api/bus/order', data: { start: orderForm.value.start, end: orderForm.value.end, path: orderForm.value.path, price: Number(orderForm.value.price), status: 0 } }); uni.showToast({ title: '订单创建成功', icon: 'success' }); // 重置表单 orderForm.value = { start: '', end: '', path: '', price: '', status: 0 }; // 刷新订单列表 fetchOrders(); } catch (error) { uni.showToast({ title: error.data?.msg || '订单创建失败', icon: 'none' }); } }; // 获取订单列表 const fetchOrders = async () => { orderLoading.value = true; try { const result = await getHttp({ url: '/prod-api/api/bus/order/list', params: { pageNum: 1, pageSize: 10 } }); orders.value = result.data.rows || []; } catch (error) { uni.showToast({ title: error.data?.msg || '获取订单失败', icon: 'none' }); } finally { orderLoading.value = false; } }; // 支付订单 const showPayPopup = (order) => { currentOrder.value = order; payPopup.value.open(); }; const closePayPopup = () => { payPopup.value.close(); }; const handlePaymentMethodChange = (e) => { paymentType.value = e.detail.value; }; const payOrder = async () => { try { const result = await getHttp({ url: '/prod-api/api/bus/pay', data: { orderNum: currentOrder.value.orderNum, paymentType: paymentType.value } }); uni.showToast({ title: '支付成功', icon: 'success' }); closePayPopup(); fetchOrders(); } catch (error) { uni.showToast({ title: error.data?.msg || '支付失败', icon: 'none' }); } }; // 取消订单 const cancelOrder = async (orderId) => { try { uni.showLoading({ title: '处理中...' }); await postHttp({ url: '/prod-api/api/bus/order/cancel', data: { orderId } }); uni.showToast({ title: '订单已取消', icon: 'success' }); fetchOrders(); } catch (error) { uni.showToast({ title: error.data?.msg || '取消失败', icon: 'none' }); } finally { uni.hideLoading(); } }; // 状态显示 const getStatusText = (status) => { const statusMap = { 0: '待支付', 1: '已支付', 2: '已完成', 3: '已取消' }; return statusMap[status] || '未知'; }; const getStatusClass = (status) => { const classMap = { 0: 'status-pending', 1: 'status-paid', 2: 'status-completed', 3: 'status-canceled' }; return classMap[status] || ''; }; // 初始化 onMounted(() => { fetchOrders(); }); </script> <style lang="scss" scoped> /* 新增弹窗样式 */ .popup-content { padding: 30rpx; .popup-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30rpx; .popup-title { font-size: 36rpx; font-weight: bold; color: #333; } } .result-list { max-height: 60vh; .empty-result { padding: 30rpx; text-align: center; color: #999; } .result-item { padding: 20rpx; border-bottom: 1rpx solid #eee; .result-name { display: block; font-size: 32rpx; color: #333; margin-bottom: 10rpx; } .result-line { font-size: 28rpx; color: #666; } } } } .bus-wrap { padding: 20rpx; background-color: #f0f8ff; } .bus-stops { overflow-y: scroll; margin: 20rpx 0; padding: 20rpx; background-color: #ffffff; border-radius: 16rpx; box-shadow: 0rpx 4rpx 8rpx rgba(0, 0, 0, 0.1); .stop-item { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 0; border-bottom: 1px solid rgba(255, 255, 255, 0.3); &:last-child { border-bottom: none; } .stop-name { font-size: 32rpx; color: #fff; } .stop-sequence { font-size: 28rpx; color: #fff; } } .highlight { color: #ff9800; } } /* 新增订单相关样式 */ .order-section, .order-list-section { background-color: #fff; border-radius: 16rpx; padding: 30rpx; margin: 20rpx 0; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); .section-title { font-size: 32rpx; font-weight: bold; color: #333; margin-bottom: 20rpx; display: flex; justify-content: space-between; align-items: center; } } .form-item { margin-bottom: 20rpx; .label { display: block; font-size: 28rpx; color: #666; margin-bottom: 10rpx; } .input { width: 100%; padding: 20rpx; border: 1rpx solid #ddd; border-radius: 8rpx; font-size: 28rpx; } } .submit-btn, .confirm-pay-btn { background-color: #4a90e2; color: #fff; border-radius: 50rpx; font-size: 30rpx; margin-top: 20rpx; } .order-item { padding: 20rpx 0; border-bottom: 1rpx solid #eee; &:last-child { border-bottom: none; } } .order-header { display: flex; justify-content: space-between; margin-bottom: 15rpx; } .order-status { font-size: 26rpx; padding: 4rpx 12rpx; border-radius: 20rpx; &.status-pending { color: #f39c12; background-color: #fff4e5; } &.status-paid { color: #2ecc71; background-color: #e8f8f0; } } .order-actions { display: flex; justify-content: flex-end; margin-top: 20rpx; button { margin-left: 20rpx; font-size: 26rpx; padding: 10rpx 20rpx; border-radius: 30rpx; &.pay-btn { background-color: #4a90e2; color: #fff; } &.cancel-btn { background-color: #fff; color: #666; border: 1rpx solid #ddd; } } } .loading { display: flex; justify-content: center; padding: 50rpx 0; } .empty { text-align: center; padding: 50rpx 0; color: #999; } .pay-popup { padding: 30rpx; .pay-amount { display: block; font-size: 36rpx; font-weight: bold; color: #ff6b6b; margin: 20rpx 0; } .payment-method { display: flex; align-items: center; padding: 20rpx 0; border-bottom: 1rpx solid #eee; } } </style> <template> <view class="buys"> <!-- 新闻列表 --> <view class="list"> <view class="buysitem" v-for="item in currentBuysList" :key="item.id" @click="toBuysDetail(item.id)"> <slot name="itemSlot" v-bind="item"></slot> </view> </view> </view> </template> <script setup> import { computed, ref } from 'vue'; import { ip, getHttp } from '../../utils/http.js' //路线列表 const buysList=ref([]) //当前路线列表内容 const currentBuysList=ref([]) //全部路线列表 async function getBuysList() { const result = await getHttp({ url: '/prod-api/api/bus/line/list' }) buysList.value = result.data.rows currentBuysList.value = buysList.value } //跳转路线详情页面 const toBuysDetail=(id)=>{ uni.navigateTo({ url:'/pages/Subway/Subway?id='+id }) } getBuysList() </script> <style lang="scss"> .buys { padding: 20rpx; background-color: #f5f5f5; } .list { display: flex; flex-direction: column; gap: 20rpx; } .buysitem { background-color: #fff; border-radius: 16rpx; box-shadow: 0rpx 4rpx 8rpx rgba(0, 0, 0, 0.1); padding: 20rpx; display: flex; align-items: center; justify-content: space-between; transition: transform 0.2s; &:hover { transform: scale(1.0); } .info { flex: 1; margin-right: 20rpx; .title { font-size: 29rpx; color: #333; margin-bottom: 10rpx; } .details { font-size: 26rpx; color: #666; text { display: block; margin: 5rpx 0; } } } .price { font-size: 32rpx; color: #ff6600; font-weight: bold; } } </style>
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值