#include <iostream>
#include <vector>
#include <utility>
using namespace std;
// 定义景点结构体
struct Attraction {
int playTime; // 景点游玩时间
};
// 动态规划函数
pair<vector<int>, int> findOptimalPlan(int n, int dailyLimit, int totalLimit, vector<Attraction>& attractions, vector<vector<int>>& transTimes) {
// dp数组,dp[i][j]表示在游玩第i个景点时,已使用j的时间,所能获得的最大游玩时间
vector<vector<int>> dp(n + 1, vector<int>(totalLimit + 1, 0));
// 记录路径
vector<vector<int>> path(n + 1, vector<int>(totalLimit + 1, -1));
// 动态规划求解
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= totalLimit; ++j) {
// 不游玩当前景点
dp[i][j] = dp[i - 1][j];
path[i][j] = 0;
// 尝试游玩当前景点
if (j >= attractions[i - 1].playTime) {
int prevTime = j - attractions[i - 1].playTime;
if (prevTime >= 0 && prevTime <= dailyLimit) {
int newTime = dp[i - 1][prevTime] + attractions[i - 1].playTime;
if (newTime > dp[i][j]) {
dp[i][j] = newTime;
path[i][j] = 1;
}
}
}
// 尝试从前一个景点过来
for (int k = 0; k < i; ++k) {
if (j >= transTimes[k][i - 1]) {
int prevTime = j - transTimes[k][i - 1];
if (prevTime >= 0 && prevTime <= dailyLimit) {
int newTime = dp[k][prevTime];
if (newTime > dp[i][j]) {
dp[i][j] = newTime;
path[i][j] = k + 1;
}
}
}
}
}
}
// 根据路径回溯找到最优解
vector<int> optimalPath;
int j = totalLimit;
for (int i = n; i >= 1; --i) {
if (path[i][j] == 1) {
optimalPath.push_back(i);
j -= attractions[i - 1].playTime;
} else if (path[i][j] > 1) { // 如果是景点编号,则加入路径
optimalPath.push_back(path[i][j]);
j -= transTimes[path[i][j] - 1][i - 1];
}
}
// 计算总游玩时间
int totalPlayTime = 0;
for (int i : optimalPath) {
totalPlayTime += attractions[i - 1].playTime;
}
// 返回最优路径和总游玩时间
return make_pair(optimalPath, totalPlayTime);
}
int main() {
// 景点数量
int n = 4;
// 每天游玩时间限制
int dailyLimit = 8;
// 总游玩时间限制
int totalLimit = 16;
// 每个景点的游玩时间
vector<Attraction> attractions = {{3}, {4}, {2}, {5}};
// 每两个景点之间的交通时间(矩阵形式)
vector<vector<int>> transTimes = {
{0, 1, 2, 1},
{1, 0, 2, 1},
{2, 2, 0, 1},
{1, 1, 1, 0}
};
// 调用函数获取最优路径和总游玩时间
pair<vector<int>, int> result = findOptimalPlan(n, dailyLimit, totalLimit, attractions, transTimes);
// 输出最优路径和总游玩时间
cout << "最优游玩方案: ";
for (int i = result.first.size() - 1; i >= 0; --i) {
cout << result.first[i] << " ";
}
cout << endl;
cout << "总游玩时间: " << result.second << " 小时" << endl;
return 0;
}