初始思路:问题所在
//思路:Dijkstra算法,找最短路径, 点权:最大,如果多种,则给出平均点权最大的路径。
//实现:字符串对应编号处理;————————终点是ROM————记录。
// 求最大happy————满足路径上的传递————最优子结构:
//要求:记录中间路径, 记录最短路径数目。
//补不足:边权点权的初始化,递推
//改正:彻彻底底弄清题意:cost最少的路径,多条则happy总和最大,
//多条则路径的平均距离最小--->保证最小。------->所以DFS实现。
//1003---->对比
#include<bits/stdc++.h>
#define MAXN 205
#define inf 0x3fffffff
using namespace std;
int e[MAXN][MAXN], d[MAXN], happy[MAXN], h[MAXN], num[MAXN];
vector<int> path;
bool vis[MAXN];
int n, k, nummember;
map<int, string> is;
map<string, int> si;
int change(string s){
if(si.find(s)!=si.end())
return si[s];
else{
si[s] = nummember;
is[nummember] = s;
return nummember++;
}
}
int main(){
string start;
cin >> n >> k >> start;
int s = change(start), endnum;
for(int i = 1; i < n; i++){ //-----> 可用一个自动排序替换。
int hy;
string station;
cin >> station >> hy;
int num = change(station);
if(station == "ROM") endnum = num;
happy[num] = hy;
}
for(int i = 0; i < k; i++){
string s1, s2;
int n1, n2, cost;
cin >> s1 >> s2 >> cost;
n1 = si[s1];
n2 = si[s2];
e[n1][n2] = e[n2][n1] = cost;
}
fill(d, d+MAXN, inf);
d[s] = 0;
fill(vis, vis+MAXN, false);
num[s] = 1; //边权,点权的初始化。
h[s] = happy[s];
for(int j = 0; j < n; j++){
int u = -1, mind = inf;
//节点从0到n-1
for(int i = 0; i < n; i++){
if(vis[i] == false && d[i] < mind){
u = i;
mind = d[i];
}
}
if(u == -1) break;
vis[u] = true;
path.push_back(u);
if(u == endnum) break;
//递推出现了问题,距离d没有更新。
//重点:递推在哪,实现什么
for(int i = 0; i < n; i++){ //点权,边权,递推在优化的这里:一个点可被多次优化。
if(vis[i] == false && e[u][i] && d[i] > d[u]+e[u][i]){
d[i] = d[u] + e[u][i];
num[i] = num[u]; //递推:最优子结构
h[i] = h[u]+happy[i];
}else if(vis[i] == false && e[u][i] && d[i] == d[u]+e[u][i]){
num[i] += num[u];
if(h[i] < h[u] + happy[i])
h[i] = h[u] + happy[i];
}
}
}
cout << num[endnum] << " " << d[endnum] << " " << h[endnum] << " " << h[endnum]/path.size() << endl;
for(int i = 0; i < path.size(); i++){
if(!i) cout << is[path[i]];
else cout <<"->" << is[path[i]];
}
return 0;
}
整理之后AC代码:
//修改---->自己写:Dijkstra+DFS ------> 对比1020
//解决的是:先解决cost--->最短路径找到----->Dijkstra
// 然后找到满足点权的路径--------->DFS
#include<bits/stdc++.h>
#define MAXN 205
#define inf 0x3fffffff
using namespace std;
int e[MAXN][MAXN], d[MAXN], happy[MAXN];
vector<int> path, temppath;
vector<int> pre[MAXN];
bool vis[MAXN];
int n, k, maxave = -1, maxsum = -1; //错因:读懂题目真的很重要
map<int, string> is;
map<string, int> si;
int cnt = 0;//求最短路径数目
void DFS(int num){
temppath.push_back(num);
if(num == 1){
cnt++;
int sum = 0;
for(int i = 0; i < temppath.size(); i++){
sum += happy[temppath[i]];
}
if(sum > maxsum){
maxsum = sum;
path = temppath;
maxave = sum / (temppath.size()-1); //错因:缺少maxave的初始化
}else if(sum == maxsum){
if(sum / temppath.size() > maxave){
maxave = sum / (temppath.size()-1); //错因:起始点为0,不计入总求平均值中
path = temppath;
}
}
temppath.pop_back();
return;
}
for(int i = 0; i < pre[num].size(); i++)
DFS(pre[num][i]);
temppath.pop_back();
}
int main(){
string start;
cin >> n >> k >> start;
si[start] = 1;
is[1] = start;
for(int i = 2; i <= n; i++){ //-----> 可用一个自动排序替换。
int hy;
string station;
cin >> station >> hy;
si[station] = i;
is[i] = station;
happy[i] = hy;
}
for(int i = 0; i < k; i++){
string s1, s2;
int n1, n2, cost;
cin >> s1 >> s2 >> cost;
n1 = si[s1];
n2 = si[s2];
e[n1][n2] = e[n2][n1] = cost;
}
fill(d, d+MAXN, inf);
d[1] = 0;
fill(vis, vis+MAXN, false);
for(int j = 0; j < n; j++){
int u = -1, mind = inf;
//节点从1到n
for(int i = 1; i <= n; i++){
if(vis[i] == false && d[i] < mind){
u = i;
mind = d[i];
}
}
if(u == -1) break;
vis[u] = true;
for(int i = 1; i <= n; i++){ //点权,边权,递推在优化的这里:一个点可被多次优化。
if(vis[i] == false && e[u][i] && d[i] > d[u]+e[u][i]){
d[i] = d[u] + e[u][i];
pre[i].clear();
pre[i].push_back(u);
}else if(vis[i] == false && e[u][i] && d[i] == d[u]+e[u][i]){
pre[i].push_back(u);
}
}
}
int num = si["ROM"];
DFS(num);
cout << cnt << " " << d[num] << " " << maxsum << " " << maxave << endl;
for(int i = path.size()-1; i >= 0; i--){
if(i==path.size()-1) cout << is[path[i]];
else cout <<"->" << is[path[i]];
}
return 0;
}
来源:CSDN
作者:qq_43642447
链接:https://blog.csdn.net/qq_43642447/article/details/103246171