Cod sursa(job #117248)

Utilizator wefgefAndrei Grigorean wefgef Data 20 decembrie 2007 23:43:37
Problema Bibel Scor Ascuns
Compilator cpp Status done
Runda Marime 2.25 kb
#include <cassert>
#include <cstdio>
#include <climits>
#include <vector>
#include <algorithm>

using namespace std;

#define maxL 17

struct pnt {
	int x, y;
};

int M;
vector<pnt> curr;
vector<int> curr_dist;

vector<pnt> last;
vector<int> last_dist;

int mat[1 << maxL][maxL];

inline int dist(const pnt& p1, const pnt& p2) {
#define SQR(x) ((x)*(x))
	return SQR(p1.x-p2.x) + SQR(p1.y-p2.y);
#undef SQR
}

int do_din() {
	memset(mat, 0xff, sizeof(mat));

	for (int j = 0; j < (int)curr.size(); ++j) {
		int& ret = mat[1 << j][j];
		ret = INT_MAX;

		for (int i = 0; i < (int)last.size(); ++i)
			ret = min(ret, dist(last[i], curr[j]) + last_dist[i]);
	}

	int prec[maxL][maxL];
	for (int i = 0; i < (int)curr.size(); ++i)
		for (int j = 0; j < (int)curr.size(); ++j) {
			prec[i][j] = dist(curr[i], curr[j]);
		}

	for (int conf = 0; conf < (1 << curr.size()); ++conf) {
		int temp[maxL], count = 0;
		for (int i = 0; i < maxL; ++i)
			if (conf & (1 << i)) temp[count++] = i;

		for (int last = 0; last < (int)curr.size(); ++last) {
			if (!(conf & (1 << last))) continue;
			if (conf == (1 << last)) continue;

			int& ret = mat[conf][last];
			ret = INT_MAX;

			conf ^= 1 << last;

			for (int i = 0; i < count; ++i)
				if (temp[i] != last)
					ret = min(ret, mat[conf][temp[i]] +
							       prec[temp[i]][last]);

			conf ^= 1 << last;
		}
	}

	for (int j = 0; j < (int)curr.size(); ++j)
		curr_dist.push_back(mat[(1 << curr.size()) - 1][j]);
	return *min_element(curr_dist.begin(), curr_dist.end());
}

int main() {
	freopen("bibel.in", "rt", stdin);
	freopen("bibel.out", "wt", stdout);

	last.push_back((pnt){0, 0});
	last_dist.push_back(0);

	while (1) {
		int op;
		scanf("%d", &op);
		assert(0 <= op && op <= 2);

		switch (op) {
		case 0: {
				int x, y;
				scanf("%d %d", &x, &y);
				assert(0 <= x && x <= 10000);
				assert(0 <= y && y <= 10000);

				curr.push_back((pnt){x, y});
				break;
			}

		case 1:	{
				assert(curr.size() <= maxL);

				int result = do_din();
				printf("%d\n", result);

				curr.swap(last);
				curr.clear();

				curr_dist.swap(last_dist);
				curr_dist.clear();
				break;
			}

		case 2: {
				return 0;
			}
		}
	}

	return 0;
}