観光名所が人気になると、「ネット赤スポット」と呼ばれます。誰もがインターネットの有名人スポットに遊びに来ます、通称「チェックイン」。さまざまなインターネットの有名スポットにチェックインする、手っ取り早く(節約して)ハッピー(お金)にする方法を「戦略」と呼びます。あなたの仕事は、インターネットの有名人の各ポイントに 1 回だけチェックインでき、多数の戦略の中から途中で費やすお金が最も少ないものを見つけることです。
入力形式:
まず、最初の行は 2 つの正の整数を与えます:インターネット有名人ポイントの数N (1< N ≤ 200) とインターネット有名人ポイント間のパスの数Mです。M行が続き、各行にはアクセスできる 2 つのインターネット有名人ポイントと、この道路での移動費用 (正の整数) が与えられます。形式は「インターネット有名人ポイント 1 インターネット有名人ポイント 2 費用」です。インターネット有名人ポイントは次から始まります。 1 からNの番号; 同時に、インターネットの有名人ポイントにあなたの家の費用も与えられ、形式は同じで、あなたの家の番号は 0 に固定されます。
次の行では、テストする戦略の数を表す正の整数Kを示します。K行が続き、各行にはチェックする戦略が示されます。形式は次のとおりです。
n V 1 V 2 ⋯ Vn
このうち、n (≤200) は戦略内のインターネット有名人ポイントの数、Viはパス上のインターネット有名人ポイントの数です。ここでは、自宅から出発し、 V 1 からチェックインし、最後にVnから帰宅すると仮定します。
出力フォーマット:
1行目に要件を満たすストラテジーの数を出力します。
2 行目では、まず、各インターネット有名ポイントに 1 回だけチェックインし、移動時間を最小限に抑える戦略のシーケンス番号 (1 から始まる) を出力し、次にこの戦略の旅費の合計を出力します。 、スペースで区切ります。このようなストラテジが一意でない場合は、シーケンス番号が最も小さいストラテジを出力します。
このタイトルでは、少なくとも 1 つの効果的な戦略が存在し、旅費の合計が 109 を超えないことを保証しています。
入力サンプル:
6 13
0 5 2
6 2 2
6 0 1
3 4 2
1 5 2
2 5 1
3 1 1
4 1 2
1 6 1
6 3 2
1 2 1
4 5 3
2 0 2
7
6 5 1 4 3 6 2
6 5 2 1 6 3 4
8 6 2 1 6 3 4 5 2
3 2 1 5
6 6 1 3 4 5 2
7 6 2 1 3 4 5 2
6 5 2 1 4 3 6
出力例:
3
5 11
説明例:
第 2 条、第 3 条、第 4 条、および第 6 条は、ガイドの基本要件を満たしていません。つまり、自宅から出発し、各インターネット有名ポイントで 1 回だけチェックインし、自宅に戻ることは不可能です。したがって、条件を満たす戦略は 3 つあります。
最初の戦略の総移動コストは次のとおりです: (0->5) 2 + (5->1) 2 + (1->4) 2 + (4->3) 2 + (3->6) 2 + ( 6->2) 2 + (2->0) 2 = 14;
5 番目の戦略の総旅費も同様に計算できます。1 + 1 + 1 + 2 + 3 + 1 + 2 = 11 となり、これはより経済的な戦略です。
7 番目の戦略の旅費の合計は、同じ方法で計算できます: 2 + 1 + 1 + 2 + 2 + 2 + 1 = 11。これは 5 番目の戦略の費用と同じですが、シリアル番号が大きくなります。なので出力されません。
私は Liushen さんのコードを見て、次のように理解しました
。
1. 隣接行列は、右の無向グラフを格納するために使用されます。
2. Has 配列を使用してチェックインが実行された回数を確認します。複数のテスト ケースの場合、ループに入るたびに 0 に初期化する必要があります。ホームに戻りますが、パスに保存する必要はありません。配列
3. すべてのインターネット有名人ポイントの数と 1 つの入力のみは、インターネット有名人ポイントの数より大きくても小さくてもならず、等しい場合は重複できません (既存の繰り返しは Has[0]=1) , 上記 2 つのいずれかに違反すると、条件は満たされなくなり、次のグループにスキップします。 3.
満たされた場合は、総コストを計算します。まあ、ここには別の状況があります。私も満足しています。上の点の数は同じで重複点はないが、接続された 2 つの場所の間に道路がありません。道路がない場合は、フラグ = 1 をマークします (最も外側のループではなく、内側のループからのみ飛び出します。これを 1 とマークすると、コストを見つけるために次の Number ++ コードを実行する必要はありません)、その後ジャンプするか、隣接する 2 つのポイントのコストを合計します
。すべての層の条件を除外し、cnt++ を満たし、最小のコストとそれに対応するシリアル番号を求めます (これより小さいものがあればコストと番号を更新します。最小の場合、コードは実行されず、更新されません。大きいシリアル番号は出力されません)
交流:
#include<bits/stdc++.h>
using namespace std;
int Edge[210][210],Path[210],Has[210],cnt,mcost=0x3f3f3f3f,id;
int main()
{
int N,M;
cin>>N>>M;
int u,v,w;
for(int i=0;i<M;i++)
{
cin>>u>>v>>w;
Edge[u][v]=Edge[v][u]=w;
}
int k;
cin>>k;
for(int i=1;i<=k;i++){
int n;
cin>>n;
fill(Has,Has+N+1,0);
Path[N+1]=0;
int flag=0,cost=0;
for(int j=1;j<=n;j++)
{
cin>>Path[j];
if(Has[Path[j]]) Has[0]=1;
Has[Path[j]]=1;
}
if(Has[0]||n!=N) continue;
for(int j=1;j<=n+1;j++)
{
if(!Edge[Path[j-1]][Path[j]]) {flag=1;break;}
cost+=Edge[Path[j-1]][Path[j]];
}
if(!flag)
{
cnt++;
if(cost<mcost) id=i,mcost=cost;
}
}
cout<<cnt<<'\n'<<id<<" "<<mcost;
}