AtCoder

ABC073 D問題(joisino’s travel)を解く

AtCoder_ABC073_D

AtCoder が提供しているABC(AtCoder Beginner Contest)073 D問題をC++で解いてみました。ABC073は、2017年9月9日21:00に実施されました。

AtCoder の紹介はこちらに、プログラミングの方針はこちらに記事があります。

D問題 joisino’s travel(Difficulty : 1345)

問題の詳細は、リンク先をご覧ください。

ABC073 D問題 joisino’s travel

すべての町の間の最短距離を求めて順列全探索します。AtCoder Problems による Difficulty は 1345 でした。

解答案

C++ プログラム例(ABC073D)

前準備としてすべての町の間の最短距離を求めます。町の数 N は、2N200 です。ワーシャル・フロイド法を用いる場合、計算量は、O(N3) であるため、最大でも 2003=8×106 となり間に合います。

次にすべての順列について全探索します。next_permutation を用います。順列の長さ R は、2Rmin(8,N) であるため、最大でも 8!=40320 であり、こちらも間に合います。

以下が、C++プログラムです。

#include <bits/stdc++.h>
using namespace std;

#define INF (1 << 30)

int main()
{
	int n, m, R;
	cin >> n >> m >> R;
	vector<int> r(R);
	for (int i = 0; i < R; ++i) {
		cin >> r[i];
		--r[i];
	}

	vector<vector<int>> dist(n, vector<int>(n, INF));
	for (int i = 0; i < n; ++i) {
		dist[i][i] = 0;
	}
	for (int i = 0; i < m; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		--a;
		--b;
		dist[a][b] = c;
		dist[b][a] = c;
	}

	for (int k = 0; k < n; ++k) {
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j < n; ++j) {
				if ((dist[i][k] < INF) && (dist[k][j] < INF)) {
					dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
				}
			}
		}
	}

	vector<int> p(R);
	for (int i = 0; i < R; ++i) {
		p[i] = i;
	}

	int result = INF;
	do {
		int t_result = 0;
		for (int i = 0; i < R - 1; ++i) {
			t_result += dist[r[p[i]]][r[p[i + 1]]];
		}
		result = min(result, t_result);
	} while (next_permutation(p.begin(), p.end()));

	cout << result << endl;

	return 0;
}

AC(Accepted=正しいプログラム)と判定されました。

最後に

2つの典型手法を組み合わせる良問だと思います。

引き続き ABC の問題を紹介していきます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA