Cod sursa(job #115601)

Utilizator mugurelionutMugurel-Ionut Andreica mugurelionut Data 16 decembrie 2007 18:25:58
Problema Gather Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.13 kb
#include <stdio.h>

#include <vector>
using namespace std;

#define NMAX 760
#define KMAX 16
#define INF 4294967295UL
#define QMAX 16384
#define QMAX_M1 16383
#define MAX_STATES_VALUE 32768

unsigned int bit[KMAX] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 };
vector<pair<int, pair<unsigned int, unsigned int> > > v[NMAX];
int poz[KMAX];
unsigned int dmin[KMAX][KMAX][KMAX + 1], dist[NMAX][KMAX + 1];
unsigned int dsmin[KMAX][MAX_STATES_VALUE];
int qpoz[QMAX], qk[QMAX], out[KMAX + 2];
char inq[NMAX][KMAX + 1];
int i, j, k, K, N, M, a, b, li, ls, cnt_out, s, snext, max_state;
unsigned int c, d, cnt_in, vmin;

void readInputData()
{
	freopen("gather.in", "r", stdin);
  
  scanf("%d %d %d", &K, &N, &M);

	poz[K] = 1;
  
  for (i = 0; i < K; i++)
  	scanf("%d", &poz[i]);
  
  for (i = 1; i <= N; i++)
  	v[i].clear();
  
  for (k = 0; k < M; k++)
  {
  	scanf("%d %d %d %d", &a, &b, &c, &d);
    
    v[a].push_back(make_pair(b, make_pair(c, d)));
    v[b].push_back(make_pair(a, make_pair(c, d)));
  }
}

void computeDistances()
{
	unsigned int cap, len, maxd;
  
	for (a = 0; a <= K; a++)
	{
		// init distances
		for (i = 1; i <= N; i++)
			for (k = 0; k <= K; k++)
				dist[i][k] = INF,
				inq[i][k] = 0;
          
		li = ls = 0;
		for (k = 1; k <= K; k++)
			dist[poz[a]][k] = 0;        

		// init queue
      
		qpoz[ls] = poz[a];
		qk[ls] = K;
		ls = (ls + 1) & QMAX_M1;
		inq[poz[a]][K] = 1;
     
		// Bellman-Ford-Moore
      
		while (li != ls)
		{
			i = qpoz[li];
			cap = qk[li];

			inq[i][cap] = 0;
        
			for (k = 0; k < v[i].size(); k++)
			{
				j = v[i][k].first;
				len = v[i][k].second.first;
				maxd = v[i][k].second.second;
          
				if (cap < maxd)
					maxd = cap;
          
				if (INF - len >= dist[i][cap] && dist[i][cap] + len < dist[j][maxd])
				{
					dist[j][maxd] = dist[i][cap] + len;

					if (!inq[j][maxd])
					{
						qpoz[ls] = j;
						qk[ls] = maxd;
						ls = (ls + 1) & QMAX_M1;
						inq[j][maxd] = 1;
					}
				}
			}
				
			li = (li + 1) & QMAX_M1;
		}
		
		for (b = 0; b <= K; b++)
			if (b != a)
			{
				dmin[a][b][K] = dist[poz[b]][K];
				
				for (k = K - 1; k >= 0; k--)
				{
					dmin[a][b][k] = dist[poz[b]][k];
					
					if (dmin[a][b][k + 1] < dmin[a][b][k])
						dmin[a][b][k] = dmin[a][b][k + 1];
				}
			}
	}
}

void computeStates()
{
	max_state = bit[K];
	
	// init state distances
	for (k = 0; k <= K; k++)
		for (s = 0; s < max_state; s++)
			dsmin[k][s] = INF;
			
	dsmin[K][0] = 0;
	
	for (s = 0; s < max_state; s++)
	{
		cnt_in = 1;
		cnt_out = 0;
		
		for (i = 0; i < K; i++)
			if ((s & bit[i]) > 0) 
				cnt_in++;
			else
				out[cnt_out++] = i;

		for (k = 0; k <= K; k++)
			if (dsmin[k][s] < INF)
			{
				// expand forward
				for (j = 0; j < cnt_out; j++)
				{
					i = out[j];
					snext = s | bit[i];
					
					if (INF / dmin[k][i][cnt_in - 1] >= cnt_in &&
					INF - cnt_in * dmin[k][i][cnt_in - 1] >= dsmin[k][s] && 
					dsmin[k][s] + dmin[k][i][cnt_in - 1] * cnt_in < dsmin[i][snext])
						dsmin[i][snext] = dsmin[k][s] + dmin[k][i][cnt_in - 1] * cnt_in;
						
						//fprintf(stderr, "updating (k=%d,s=%d)/d=%u,cnt_in=%d -> (k=%d,snext=%d)/d=%u\n", k, s, dsmin[k][s], cnt_in, i, snext, dsmin[i][snext]);
				}
			}
	}
}

void writeOutputData()
{
	vmin = INF;
	
	for (i = 0; i <= K; i++)
		if (dsmin[i][max_state - 1] < vmin)
			vmin = dsmin[i][max_state - 1];
	
	freopen("gather.out", "w", stdout);
	printf("%u\n", vmin);
}

void printInfo()
{
	for (a = 0; a <= K; a++)
		for (b = 0; b <= K; b++)
		{
			fprintf(stderr, "### %d(%d) -> %d(%d)\n", a, poz[a], b, poz[b]);
			
			for (k = 0; k <= K; k++)
				fprintf(stderr, "------ k=%d -> dist=%u\n", k, dmin[a][b][k]);
		}
		
	for (s = 0; s < max_state; s++)
	{
		fprintf(stderr, "### state=%d\n", s);
		
		for (k = 0; k <= K; k++)
			fprintf(stderr, "------- k=%d -> dsmin=%u\n", k, dsmin[k][s]);
	}
}

int main()
{
	readInputData();
	computeDistances();
  computeStates();
	writeOutputData();
	//printInfo();
	
	return 0;
}