题目
题目链接
解题思路
这是一道动态规划和期望计算的问题,主要思路如下:
-
问题分析:
- \(n\) 个景点构成无向图
- 每个景点参观需要 \(m_i\) 时间,增加愉悦度 \(v1_i\) 和 \(v2_i\)
- 景点间通过 \(m\) 条路径连接,每条路径耗时 \(t_i\)
- 总游玩时间为 \(k\) 分钟
- 需要计算游游和小伙伴的期望愉悦度
-
解决方案:
- 使用动态规划计算期望值
- \(dp[i][j]\) 表示剩余 \(i\) 时间在 \(j\) 点的期望愉悦度
- 考虑每个景点的游玩时间和路径选择
- 分别计算两个人的期望值
-
实现细节:
- 使用邻接表存储图结构
- 处理随机选择的概率计算
- 注意浮点数精度
代码
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;struct Site {int m; // 游玩时间double v[2]; // 两人的愉悦度
};struct Path {int d; // 目标景点int t; // 路径时间
};// 计算期望愉悦度
double getExpectation(vector<Site>& sites, vector<vector<Path>>& paths, int k, int p) {int n = sites.size();// dp[i][j]表示剩余i时间在j点的期望愉悦度vector<vector<double>> dp(k + 1, vector<double>(n, 0));for (int i = 1; i <= k; i++) {for (int j = 0; j < n; j++) {double temp = 0;int count = 0;// 如果时间足够游玩当前景点if (i >= sites[j].m) {dp[i][j] += sites[j].v[p];}// 考虑所有可达的下一个景点for (const Path& path : paths[j]) {if (i >= (path.t + sites[j].m + sites[path.d].m)) {temp += dp[i - path.t - sites[j].m][path.d];count++;}}// 计算期望值if (count) {dp[i][j] += temp / count;}}}// 计算最终期望double res = 0;for (int i = 0; i < n; i++) {res += dp[k][i];}return res / n;
}int main() {int n, m, k;while (cin >> n >> m >> k) {// 读入景点信息vector<Site> sites(n);for (int i = 0; i < n; i++) {cin >> sites[i].m >> sites[i].v[0] >> sites[i].v[1];}// 读入路径信息vector<vector<Path>> paths(n);for (int i = 0; i < m; i++) {int x, y, t;cin >> x >> y >> t;x--; y--;paths[x].push_back({y, t});paths[y].push_back({x, t});}// 计算两人的期望愉悦度double res1 = getExpectation(sites, paths, k, 0);double res2 = getExpectation(sites, paths, k, 1);cout << fixed << setprecision(5) << res1 << " " << res2 << endl;}return 0;
}
import java.util.*;public class Main {static class Site {int m;double[] v = new double[2];}static class Path {int d, t;Path(int d, int t) {this.d = d;this.t = t;}}static double getExpectation(Site[] sites, List<Path>[] paths, int k, int p) {int n = sites.length;double[][] dp = new double[k + 1][n];for (int i = 1; i <= k; i++) {for (int j = 0; j < n; j++) {double temp = 0;int count = 0;if (i >= sites[j].m) {dp[i][j] += sites[j].v[p];}for (Path path : paths[j]) {if (i >= (path.t + sites[j].m + sites[path.d].m)) {temp += dp[i - path.t - sites[j].m][path.d];count++;}}if (count > 0) {dp[i][j] += temp / count;}}}double res = 0;for (int i = 0; i < n; i++) {res += dp[k][i];}return res / n;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (sc.hasNext()) {int n = sc.nextInt();int m = sc.nextInt();int k = sc.nextInt();Site[] sites = new Site[n];for (int i = 0; i < n; i++) {sites[i] = new Site();sites[i].m = sc.nextInt();sites[i].v[0] = sc.nextDouble();sites[i].v[1] = sc.nextDouble();}@SuppressWarnings("unchecked")List<Path>[] paths = new List[n];for (int i = 0; i < n; i++) {paths[i] = new ArrayList<>();}for (int i = 0; i < m; i++) {int x = sc.nextInt() - 1;int y = sc.nextInt() - 1;int t = sc.nextInt();paths[x].add(new Path(y, t));paths[y].add(new Path(x, t));}double res1 = getExpectation(sites, paths, k, 0);double res2 = getExpectation(sites, paths, k, 1);System.out.printf("%.5f %.5f%n", res1, res2);}sc.close();}
}
class Site:def __init__(self):self.m = 0self.v = [0, 0]class Path:def __init__(self, d, t):self.d = dself.t = tdef get_expectation(sites, paths, k, p):n = len(sites)dp = [[0] * n for _ in range(k + 1)]for i in range(1, k + 1):for j in range(n):temp = 0count = 0if i >= sites[j].m:dp[i][j] += sites[j].v[p]for path in paths[j]:if i >= (path.t + sites[j].m + sites[path.d].m):temp += dp[i - path.t - sites[j].m][path.d]count += 1if count:dp[i][j] += temp / countreturn sum(dp[k]) / ndef main():while True:try:n, m, k = map(int, input().split())sites = [Site() for _ in range(n)]for i in range(n):m_i, v1, v2 = map(float, input().split())sites[i].m = int(m_i)sites[i].v = [v1, v2]paths = [[] for _ in range(n)]for _ in range(m):x, y, t = map(int, input().split())x -= 1y -= 1paths[x].append(Path(y, t))paths[y].append(Path(x, t))res1 = get_expectation(sites, paths, k, 0)res2 = get_expectation(sites, paths, k, 1)print(f"{res1:.5f} {res2:.5f}")except EOFError:breakif __name__ == "__main__":main()
算法及复杂度
- 算法:动态规划
- 时间复杂度:\(\mathcal{O}(k * n * m)\) - \(k\) 为总时间,\(n\) 为景点数,\(m\) 为平均路径数
- 空间复杂度:\(\mathcal{O}(k * n)\) - 动态规划数组大小