Cod sursa(job #25536)

Utilizator mugurelionutMugurel-Ionut Andreica mugurelionut Data 4 martie 2007 12:53:05
Problema Magazin Scor 80
Compilator cpp Status done
Runda preONI 2007, Runda 3, Clasele 11-12 Marime 4.04 kb
#include <stdio.h>
#include <string.h>

#define NMAX 30103
#define MMAX 30
#define INF 66666666

char prod[NMAX][MMAX];
int dmin[NMAX][2][2]; // distanta minima pt a ajunge in dreptul culoarului i, 0-jos / 1-sus, cu culoarul 0-uncleared/1-cleared
int pmin[NMAX], pmax[NMAX], bestgain[NMAX], np[NMAX], sbg[NMAX];
int dq[4][NMAX], li[4], ls[4];
int i, j, k, P, N, M, D, v;

int main()
{
	freopen("magazin.in", "r", stdin);

	scanf("%d%d%d%d", &P, &N, &M, &D);
	M++;

	memset(prod, 0, sizeof(prod));

	for (k = 1; k <= P; k++)
	{
		scanf("%d%d", &i, &j);
		prod[i][j] = 1;
	}

	for (k = 1; k <= N; k++)
	{
		// proceseaza culoarul k

		prod[k][0] = 1;
		prod[k][M] = 1;

		pmin[k] = M;
		pmax[k] = 0;

		for (i = 1; i < M; i++)
			if (prod[k][i])
			{
				pmin[k] = i;
				break;
			}

		for (i = M - 1; i >= 1; i--)
			if (prod[k][i])
			{
				pmax[k] = i;
				break;
			}

		np[k] = 0;

		for (i = 1; i < M; i++)
			if (prod[k][i])
				np[k]++;

		bestgain[k] = 0;

		for (i = 0; i < M; i++)
			if (prod[k][i])
				for (j = i + 1; j <= M; j++)
					if (prod[k][j])
					{
						if (j - i > bestgain[k])
							bestgain[k] = j - i;

						break;
					}
	}

	sbg[N + 1] = 0;

	for (k = N; k >= 1; k--)
		sbg[k] = sbg[k + 1] + (bestgain[k]);

	for (k = 1; k <= N; k++)
		for (i = 0; i < 2; i++)
			for (j = 0; j < 2; j++)
				dmin[k][i][j] = INF;

	// initialize the deques

	for (i = 0; i < 4; i++)
	{
		dq[i][1] = INF;
		li[i] = ls[i] = 1;
	}

	dmin[1][0][0] = 0;

	for (k = 1; k <= N; k++)
	{
		// the deque(s) part

		for (i = 0; i < 4; i++)
		{
			v = dq[i][li[i]];

			if (i == 0)
			{
				v = v - 3 * D * (N - k) - (2 * M * (N - k + 1) - 2 * sbg[k]) + M;

				if (v < dmin[k][1][1])
					dmin[k][1][1] = v;
			}
			else
			if (i == 1)
			{
				v = v - 3 * D * (N - k) - (2 * M * (N - k + 1) - 2 * sbg[k]) + M;

				if (v < dmin[k][0][1])
					dmin[k][0][1] = v;
			}
			else
			if (i == 2)
			{
				v = v - 3 * D * (N - k) - (2 * M * (N - k) - 2 * sbg[k + 1]) + M;

				if (v < dmin[k][1][1])
					dmin[k][1][1] = v;
			}
			else
			if (i == 3)
			{
				v = v - 3 * D * (N - k) - (2 * M * (N - k) - 2 * sbg[k + 1]) + M;

				if (v < dmin[k][0][1])
					dmin[k][0][1] = v;
			}
		}

		// add values to the deque(s)

		// 0
		v = dmin[k][0][0] + 2 * M * (N - k + 1) - 2 * sbg[k] + 3 * D * (N - k);
		
		while (ls[0] >= li[0] && dq[0][ls[0]] > v)
			ls[0]--;

		ls[0]++;
		dq[0][ls[0]] = v;


		// 1
		v = dmin[k][1][0] + 2 * M * (N - k + 1) - 2 * sbg[k] + 3 * D * (N - k);
		
		while (ls[1] >= li[1] && dq[1][ls[1]] > v)
			ls[1]--;

		ls[1]++;
		dq[1][ls[1]] = v;

		// 2
		v = dmin[k][0][0] + 2 * M * (N - k) - 2 * sbg[k + 1] + 3 * D * (N - k);
		
		while (ls[2] >= li[2] && dq[2][ls[2]] > v)
			ls[2]--;

		ls[2]++;
		dq[2][ls[2]] = v;

		// 3
		v = dmin[k][1][0] + 2 * M * (N - k) - 2 * sbg[k + 1] + 3 * D * (N - k);
		
		while (ls[3] >= li[3] && dq[3][ls[3]] > v)
			ls[3]--;

		ls[3]++;
		dq[3][ls[3]] = v;

		// finished deque(s)

		// de jos in sus pe culoarul k
		if (dmin[k][0][0] + M < dmin[k][1][1])
			dmin[k][1][1] = dmin[k][0][0] + M;

		if (dmin[k][0][1] + M < dmin[k][1][1])
			dmin[k][1][1] = dmin[k][0][1] + M;

		// de sus in jos pe culoarul k
		if (dmin[k][1][0] + M < dmin[k][0][1])
			dmin[k][0][1] = dmin[k][1][0] + M;

		if (dmin[k][1][1] + M < dmin[k][0][1])
			dmin[k][0][1] = dmin[k][1][1] + M;

		// de jos, un pic in sus si inapoi jos
		if (dmin[k][0][0] + 2 * pmax[k] < dmin[k][0][1])
			dmin[k][0][1] = dmin[k][0][0] + 2 * pmax[k];

		// de sus, un pic in jos si inapoi sus
		if (dmin[k][1][0] + 2 * (M - pmin[k]) < dmin[k][1][1])
			dmin[k][1][1] = dmin[k][1][0] + 2 * (M - pmin[k]);

		// fa un pas pana la urmatorul culoar

		if (dmin[k][0][1] + D < dmin[k + 1][0][0])
			dmin[k + 1][0][0] = dmin[k][0][1] + D;

		if (dmin[k][1][1] + D < dmin[k + 1][1][0])
			dmin[k + 1][1][0] = dmin[k][1][1] + D;
	}

	freopen("magazin.out", "w", stdout);

	printf("%d\n", dmin[N][0][1]);

	return 0;
}