彩色路径 第32次CCF-CSP计算机软件能力认证
看见图就想用图去做
但是发现答案用的dp数组做:
20分:简单dp
因为只需要考虑是否超过节点个数l
1.我们定义dp[i][j]为 到达第i个节点经过j条边的最大长度
2.dp[v][j]=max(dp[v][j],dp[u][j-1]+w)
3.初始化 求最长肯定要初始化为INT_MIN
4.遍历顺序:先遍历每个结点u 再遍历对应的v
对每个v去进行1-l条边的遍历 得到经过j条的最大长度
50分:状态压缩dp
100分:看不懂
超时20分代码:
#include<bits/stdc++.h>
using namespace std;
int N, M, L, K;
struct Edge {
int to, length;
Edge(int to, int length) :to(to), length(length) {}
};
vector<int> color;//颜色标签
vector<vector<Edge>> graph;//邻接表
//vector<int> path;
int max_length = 0;//最大长度
//i:当前遍历节点
//colors:目前找到的颜色集合
//num:结点个数
void dfs(int i,set<int> colors,int num,int now_length) {
if (num > L) {
return;
}
else {
//说明找到了
if (i == N - 1) {
/*
for (int i = 0; i < path.size(); i++)
cout << path[i] << " ";
cout << endl;
*/
max_length = max(max_length, now_length);
return;
}
//没找到继续遍历
else {
for (Edge e : graph[i]) {
int to = e.to;
int length = e.length;
int col = color[to];
//说明当前颜色不存在
if (colors.find(col) == colors.end()) {
//path.push_back(to);
colors.insert(col);
dfs(to, colors, num + 1, now_length + length);
colors.erase(col);
//path.pop_back();
}
}
}
}
}
//找到最长观光路线:
//颜色各不相同 结点数小于等于L
//越长越好
void solve() {
set<int> c;
c.insert(color[0]);
dfs(0, c, 1, 0);
cout << max_length;
}
int main() {
//N:结点个数(0~N-1)
//M:边的个数
//L:理想观光路线节点上限
//K:颜色种类(0~K-1)
cin >> N >> M >> L >> K;
cin.ignore();
color.resize(N);
for (int i = 0; i < N; i++) {
cin>>color[i];
}
//重置图的大小
graph.resize(N);
vector<int> U(M), V(M), D(M);
for (int i = 0; i < M; i++) {
cin>>U[i];
}
for (int i = 0; i < M; i++) {
cin >> V[i];
}
for (int i = 0; i < M; i++) {
cin >> D[i];
}
//构建图
for (int i = 0; i < M; i++) {
Edge e = Edge(V[i], D[i]);
graph[U[i]].push_back(e);
}
solve();
return 0;
}
20分dp核心代码:
// 初始化动态规划数组
vector<vector<int>> dis(n, vector<int>(l, -inf));
dis[0][0] = 0; // 起点的初始状态
// 动态规划计算最大路径权重
for (int u = 0; u < n - 1; u++) {
for (auto tem : g[u]) {
int v = tem.first, w = tem.second;
for (int i = 1; i < l; i++) {
if (dis[u][i - 1] == -inf) continue; // 如果路径不可达,跳过
dis[v][i] = max(dis[v][i], dis[u][i - 1] + w);
}
}
}