今日の問題はこちら。
提出コードと考え方
距離を求める部分は問題ないはずなので、経路を全列挙すれば終わりです。
やったことがないと困るかもしれませんが、C++ならnext_permutationを使うのが楽です。Pythonならitertools.permutationsでしょうか。
機能を軽く説明します。
next_permutation(first, last)のように配列の範囲[first, last)を渡すと、その部分を辞書順が次に大きい順列に置き換えます。
また、この関数は次の順列が存在するときtrue、存在しないときfalseを返します。そのため、提出コードのようにdo-whileで書くのが便利です。
具体的な処理部分についてはこれで終わりですが、もう一つ。
iota(first, last, value)は配列の範囲[first, last)に「value, value+1, …」を前から順に代入するものです。
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0;i < n;i++)
vector<pair<int,int>> p(8);
double dist(int from, int to) {
int dx = p[to].first - p[from].first;
int dy = p[to].second - p[from].second;
return pow(dx * dx + dy * dy, 0.5);
}
int fact(int n){
int res = 1;
for(int i = 2;i <= n;i++) res *= i;
return res;
}
int main() {
int n;
cin >> n;
rep(i,n) cin >> p[i].first >> p[i].second;
vector<int> root(n);
iota(root.begin(),root.end(),0);
double ans = 0;
do {
rep(i,n-1) ans += dist(root[i],root[i+1]);
} while (next_permutation(root.begin(),root.end()));
ans /= fact(n);
printf("%.10lf\n",ans);
}
全列挙する問題は意外と差がつきやすいので、この機会に覚えましょう。
コメント