Cod sursa(job #115576)

Utilizator MariusMarius Stroe Marius Data 16 decembrie 2007 12:59:53
Problema Gather Scor 10
Compilator cpp Status done
Runda preONI 2008, Runda 2, Clasele 11-12 Marime 2.06 kb
#include <cstdio>
#include <vector>
#include <memory.h>

using namespace std;

const char iname[] = "gather.in";
const char oname[] = "gather.out";

#define MAXK  16
#define MAXN  755
#define MAXM  1255
#define INF   1e9
#define MIN(a, b) ((a) < (b) ? (a) : (b))

int K, N, M, P[MAXK];

int C[1 << MAXK][MAXK];

int S[MAXK], T[MAXK];

struct muchie {
	int x, y, cst, cap;
} E[MAXM];

int D[MAXN];


int h(int s, int srs, int dst)
{
	int cnt = 0;

	for (int i = 0; i < K; ++ i) if ((s >> i) & 1)
		cnt ++;
	if (cnt == 0) if (srs != 1)
		return INF;
	// cnt <= cap
	for (int i = 1; i <= N; ++ i)
		D[i] = INF;
	D[srs] = 0;
	for (int i = 1; i <= N; ++ i)
		for (int j = 0; j < M; ++ j) if (E[j].cap >= cnt) {
			if (D[E[j].x] > D[E[j].y] + E[j].cst * (cnt ? cnt : 1))
				D[E[j].x] = D[E[j].y] + E[j].cst * (cnt ? cnt : 1);
			if (D[E[j].y] > D[E[j].x] + E[j].cst * (cnt ? cnt : 1))
				D[E[j].y] = D[E[j].x] + E[j].cst * (cnt ? cnt : 1);
		}
	return D[dst];
}

void g(int i, int s, int t, int p)
{
	if (i == K) {
		for (int j = 0; j < K; ++ j) if ((s >> j) & 1)
		{
			// deplaseaza |s| detinuti de la P[j] la P[p]
			if (s && (t ^ s)) {
				C[t][p] = MIN(C[t][p], C[s][j] + C[t ^ s][p] + h(s, P[j], P[p]));
			//	printf("%d\n", s);
			}
		}
	} else if (i < K) {
		g(i+1, s, t, p);
		if ((t >> i) & 1)
			g(i+1, s | (1 << i), t, p);
	}
}

int main(void)
{
	freopen(iname, "r", stdin);
	freopen(oname, "w", stdout);

	scanf("%d %d %d", &K, &N, &M);
	for (int i = 0; i < K; ++ i)
		scanf("%d", &P[i]);
	for (int i = 0; i < M; ++ i)
		scanf("%d %d %d %d", &E[i].x, &E[i].y, &E[i].cst, &E[i].cap);
	for (int i = 0; i < 1 << MAXK; ++ i)
		for (int j = 0; j < MAXK; ++ j)	  C[i][j] = INF;
	for (int s = 1; s < 1 << K; ++ s) {
		if ((s & (s - 1)) == 0) {
			// deplasez pe G in locatie
			for (int j = 0; j < K; ++ j) if ((s >> j) & 1)
				C[s][j] = h(0, 1, P[j]);
		} else {
			for (int j = 0; j < K; ++ j) if ((s >> j) & 1)
				g(0, 0, s, j);
		//	printf(":)\n");
		}
	}
	int sup = (1 << K) - 1;
	int min = INF;
	for (int i = 0; i < K; ++ i)
		if (min > C[sup][i])	min = C[sup][i];
	printf("%d\n", min);

	return 0;
}