1087ローマに通じるすべての道路(30分)
確かに私たちの街からローマへの多くの異なる観光ルートがあります。あなたはあなたのクライアントを最も幸福を得ながら、最小のコストでルートを見つけることになっています。
入力仕様:
各入力ファイルには1つのテストケースが含まれます。いずれの場合も、最初の行には2つの正の整数N(2≤N≤200)、都市の数、およびKは都市のペア間のルートの総数です。開始都市の名前が続きます。次のN-1行はそれぞれ、都市の名前と、開始都市を除いてその都市から得られる幸福を表す整数を示します。次にK行が続き、それぞれが2つの都市間のルートをCity1 City2 Costという形式で記述します。ここでは、都市の名前は3つの大文字の英字の文字列であり、目的地は常にローマを表すROMです。
出力仕様:
各テストケースについて、最小のコストでルートを検索することになっています。そのようなルートが一意ではない場合、最大の幸福を持つルートが推奨されます。そのようなルートがまだ一意でない場合は、平均幸せ度が最大のルートを出力します。そのようなソリューションが存在し、一意であることが裁判官によって保証されています。
したがって、出力の最初の行で、4つの数値を印刷する必要があります。推奨されるルートの最小コスト、コスト、幸福、および平均幸福(整数部分のみを取る)の異なるルートの数です。次に、次の行では、City1-> City2->…-> ROMの形式でルートを印刷します。
入力例:
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
出力例:
3 3 195 97
HZH->PRS->ROM
タイトル
ノードの重み:各都市の
エッジの重み重み:各パスのコストカウントされた
エッジ:
最短パスによって渡されたノードの数をカウント最短パス:最短パスの数をカウント
保存されたパス:保存されたパスパス、後続の出力
上記のそれぞれがリストを維持する必要があります。
int D[MAXcity]; //最少花费
int mostHap[MAXcity]; //最多快乐度
int Count[MAXcity]; //最短路径的个数
int C[MAXcity]; //统计路程经过的边数
int path[MAXcity]; //记录路径
少なくとも最短はINFINITYに初期化され
、統計的側面の数は0に初期化されます。
ダイクストラのアルゴリズムを展開します。
void Dijkstra()
{
bool visited[MAXcity];
fill(D,D+MAXcity,INFINITY); //最短距离
fill(visited,visited+MAXcity,false);
fill(mostHap,mostHap+MAXcity,0);
fill(Count,Count+MAXcity,0);
fill(C,C+MAXcity,0);
D[0]=0; //自己到自己花钱0
Count[0]=1; //自己到自己有一条
path[0]=-1; //设置开头-1,方便后续入遍历输出
//
while(1)
{
int Min=INFINITY;
int V=-1;
for(int i=0;i<N;i++)
if(!visited[i]&&D[i]<Min)
{
Min=D[i];
V=i;
}
if(V==-1) break;
visited[V]=true;
for(int i=0;i<N;i++)
{
if(!visited[i]){
if(D[V]+Graph[V][i]<D[i])
{
D[i]=D[V]+Graph[V][i];
mostHap[i]=mostHap[V]+happiness[i];
Count[i]=Count[V];
C[i]=C[V]+1;
path[i]=V;
}
else if(D[V]+Graph[V][i]==D[i]){
//这里的else很关键——小于后D[i]改变,可能满足后序的==
Count[i]+=Count[V];
if(mostHap[i]<mostHap[V]+happiness[i])
{
D[i]=D[V]+Graph[V][i];
mostHap[i]=mostHap[V]+happiness[i];
path[i]=V;
C[i]=C[V]+1;
}
}
}
}
}
}
判断が等しい場合は、他の
条件を追加する必要があることに注意してください。以前の「より小さい」条件はD [i]の値を変更するため、==判断を再入力できます。各リストを維持するのは
困難
です。
要求数最短路径有多少条
count[origin] = 1;
如果找到更短路:count[i]=count[V];因为W与V只差一条边,所以两者相同;
如果找到等长路:count[i]+=count[V];登场路的数量为W前面一个点的路的数量;
要求边数最少的最短路
C[origin] = 0;
如果找到更短路:C[i]=C[V]+1;
如果找到等长路:C[i]=C[V]+1;
要求最短路径的快乐度最高
mostHap[orrgin]=0;
如果找到更短路:mostHap[i]=mostHap[V]+happiness[i]
如果找到等长路:if(mostHap[V]+happiness[i]>mostHap[i])
mostHap[i]=mostHap[V]+happiness[i];
得到路径
每个条件都加上 path[i]=V;
最后通过path[]可以一路找到出发点;
入力メソッド:
マップを使用し、names配列を開いて名前を保存し
、happiness配列を開いて各都市の幸せを保存します。
void input()
{
cin>>N>>K>>names[0]; //名称
happiness[0]=0; //幸福感
for(int i =1;i<N;i++)
{
cin>>names[i]>>happiness[i];
if(names[i]=="ROM") Rom=i;
}
for(int i=0;i<K;i++)
{
string a,b;
int x,y,cost;
cin>>a>>b>>cost;
x=Findname(names,a);
y=Findname(names,b);
Graph[x][y]=cost;
Graph[y][x]=cost;
}
}
使用されているfindname関数は単純な検索シーケンス番号です;
ハッシュテーブルマップを使用する方が便利ですが、私には使い道がありません。
int Findname(string names[],string name)
{
for(int i=0;i<N;i++)
{
if(names[i]==name)
return i;
}
}
ヘッダーファイルとメイン関数
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
#define INFINITY 65533
#define MAXcity 201
string names[MAXcity];
int happiness[MAXcity];
int Graph[MAXcity][MAXcity]; //记得初始化为正无穷
int N,K;
string start;
int Rom;
int main()
{
fill(Graph[0],Graph[0]+MAXcity*MAXcity,INFINITY);
input();
//得到图,名称,幸福感列表;
//求0到各点的最少钱,并加上幸福感
//若最少钱相等,选幸福感最大的路线
//若还相等——平均幸福感最大的——即幸福感除以路过的城市数
Dijkstra();
cout<<Count[Rom]<<" "<<D[Rom]<<" "<<mostHap[Rom]<<" "<<mostHap[Rom]/C[Rom]<<endl;
stack<int> P;
int i=Rom;
P.push(i);
while(path[i]!=-1)
{
i=path[i];
P.push(i);
}
while(!P.empty())
{
int t=P.top();
P.pop();
if(t!=Rom)
cout<<names[t]<<"->";
else cout<<names[t];
}
}